Universal migration tool for converting any CMS to FrontMatter format with automatic CMS detection and intelligent content normalization
npm install migrate.frontmatterA universal, intelligent migration tool that converts content from any CMS to FrontMatter format. No vendor-specific code required - works through automatic detection and content normalization.
⨠Universal Adapter - Works with any CMS through intelligent detection
š Auto-Detection - Automatically identifies CMS type from export structure
š§ Schema Introspection - Analyzes document fields and types automatically
š Smart Field Mapping - Maps fields using naming patterns and ML
šØ Content Normalization - Converts all rich content formats to Markdown
š¦ Media Download - Parallel downloads with retry logic and CDN support
š Plugin System - Lightweight plugins for CMS-specific edge cases
ā” Fast & Efficient - Batch processing with progress tracking
šÆ Zero Config - Works out of the box for most migrations
Works with any CMS that can export data. Specifically tested with:
- ā
WordPress
- ā
Contentful
- ā
Strapi
- ā
Sanity
- ā
TinaCMS
- ā
Payload CMS
- ā
Ghost
- ā
Custom CMS platforms
- ā
...and more!
``bashGlobal installation
npm install -g @frontmatter/migrate
Quick Start
$3
`bash
Universal migration (auto-detects CMS)
frontmatter-migrate migrate --input export.json --output ./contentInteractive mode (guided setup)
frontmatter-migrate initWith options
frontmatter-migrate migrate \
--input wordpress-export.xml \
--output ./content \
--download-media \
--media-dir ./public/images \
--format yaml-frontmatter \
--verbose
`$3
`typescript
import { UniversalAdapter } from '@frontmatter/migrate'// Create migrator
const migrator = new UniversalAdapter()
// Run migration
const result = await migrator.migrate(exportData, {
output: './content',
downloadMedia: true,
mediaDir: './public/images',
format: 'yaml-frontmatter'
})
// Check results
console.log(
Migrated ${result.stats.successfulMigrations} documents)
console.log(Detected CMS: ${migrator.getDetectedCMS()})// Save config
fs.writeFileSync('.frontmatter.yml', stringify(result.config))
`How It Works
$3
Identifies CMS from export structure by analyzing:
- Document field patterns
- Object structure and nesting
- Special identifiers (_id, _type, sys, etc.)
- Content format markers$3
Automatically understands your content structure:
- Groups documents by type/collection
- Infers field types from values
- Detects relationships between documents
- Identifies media and rich content fields$3
Maps fields using smart patterns:
`typescript
// Automatically maps these variations:
post_title, headline, name ā title
post_content, body, text ā body
created_at, publishedAt, pub_date ā date
featured_image, thumbnail, cover ā featuredImage
`$3
Converts all rich content formats to Markdown:
- HTML ā Markdown
- Portable Text (Sanity) ā Markdown
- Slate/TipTap ā Markdown
- Lexical (Payload) ā Markdown
- Mobiledoc (Ghost) ā Markdown
- Gutenberg (WordPress) ā Markdown
- Draft.js, Editor.js, Quill ā MarkdownCLI Options
`bash
frontmatter-migrate migrate [options]Options:
-i, --input Input file or URL (required)
-o, --output Output directory (default: ./content)
--cms CMS type hint (optional, auto-detected)
--download-media Download media assets (default: true)
--media-dir Media output directory (default: ./public/images)
--format Output format (yaml|json|toml-frontmatter)
--batch-size Process in batches (default: 50)
--dry-run Preview without writing files
-v, --verbose Detailed logging
--collection-name Override collection name
`Input Formats
Supports multiple input formats:
- JSON - Most modern CMS exports
- NDJSON - Newline-delimited JSON (streaming)
- XML - WordPress and older systems
- YAML/TOML - Static site generators
- CSV - Simple data exports
Output Structure
`
.
āāā .frontmatter.yml # FrontMatter configuration
āāā content/
ā āāā posts/
ā ā āāā 2024-01-15-first-post.md
ā ā āāā 2024-01-20-second-post.md
ā āāā pages/
ā āāā about.md
ā āāā contact.md
āāā public/
āāā images/
āāā hero-image.jpg
āāā thumbnail.png
`$3
`markdown
---
title: "My First Post"
date: 2024-01-15
author: "John Doe"
tags: ["tutorial", "migration"]
featuredImage: "/images/hero-image.jpg"
---Post Content
This is the post body in Markdown format...
`$3
`yaml
content:
- id: posts
name: posts
label: Posts
type: collection
path: content/posts
format: yaml-frontmatter
filename: '{year}-{month}-{day}-{slug}.md'
fields:
- name: title
label: Title
type: string
required: true
- name: date
label: Date
type: datetime
- name: author
label: Author
type: string
- name: tags
label: Tags
type: string
list: true
- name: featuredImage
label: Featured Image
type: image
`Plugins
Extend functionality with lightweight plugins for CMS-specific quirks:
`typescript
import { UniversalAdapter } from '@frontmatter/migrate'
import { wordpressPlugin } from '@frontmatter/migrate/plugins'const migrator = new UniversalAdapter([
wordpressPlugin // Handles shortcodes, Gutenberg blocks, ACF
])
`$3
-
wordpressPlugin - WordPress shortcodes, Gutenberg blocks, ACF fields
- sanityPlugin - Portable Text converter, Sanity image URLs
- contentfulPlugin - Rich text renderer, media assets
- strapiPlugin - Dynamic zones, components
- payloadPlugin - Blocks, Slate/Lexical content
- ghostPlugin - Mobiledoc/Lexical converterExamples
$3
`bash
Export from WordPress (Tools ā Export)
Then migrate
frontmatter-migrate migrate \
--input wordpress-export.xml \
--output ./content/blog \
--download-media \
--media-dir ./public/images
`$3
`bash
Export from Contentful CLI:
contentful space export --space-id xxx
frontmatter-migrate migrate \
--input contentful-export.json \
--output ./content
`$3
`bash
Export from Sanity:
sanity dataset export production export.ndjson
frontmatter-migrate migrate \
--input export.ndjson \
--output ./content
`Advanced Usage
$3
Create
migrate.config.js:`javascript
module.exports = {
input: './export.json',
output: './content', // Field mapping overrides
fieldMappings: {
'custom_field': 'customField'
},
// Collection configuration
collections: {
posts: {
path: 'content/blog',
filename: '{year}-{month}-{day}-{slug}.md'
}
},
// Media configuration
media: {
download: true,
output: 'public/images',
extensions: ['jpg', 'png', 'gif', 'svg']
}
}
`Run with config:
`bash
frontmatter-migrate migrate --config migrate.config.js
`$3
`typescript
import {
UniversalAdapter,
SchemaDetector,
IntelligentFieldMapper,
ContentNormalizer
} from '@frontmatter/migrate'// Advanced usage with custom components
const schemaDetector = new SchemaDetector()
const schema = await schemaDetector.analyzeStructure(documents)
const fieldMapper = new IntelligentFieldMapper()
const fields = fieldMapper.mapFields(doc.metadata, {
documentType: 'post',
cmsType: 'wordpress'
})
const normalizer = new ContentNormalizer()
const markdown = await normalizer.normalizeRichContent(content)
`Development
`bash
Clone repository
git clone https://github.com/mohammadzfaisal/migrate.frontmatter.git
cd migrate.frontmatterInstall dependencies
npm installBuild
npm run buildRun tests
npm testRun locally
npm run dev -- migrate --input test.json --output ./test-output
`Contributing
Contributions welcome! Please read CONTRIBUTING.md for guidelines.
$3
1. Create plugin in
src/plugins/your-cms-plugin.ts
2. Implement CMSPlugin interface
3. Add detection logic
4. Export from src/plugins/index.ts`MIT License - see LICENSE for details.
- š Documentation
- š Issue Tracker
- š¬ Discussions
- FrontMatter CMS - Content management system
- FrontMatter VSCode Extension
---
Made with ā¤ļø by Mohammad Faisal