@teagantb/payload-wordpress-migration
v1.0.3
Published
WordPress to Payload CMS migration plugin - Migrate posts, media, and content from WordPress to Payload CMS
Readme
Payload WordPress Migration Plugin
A comprehensive plugin for migrating content from WordPress to Payload CMS. This plugin enables seamless migration of posts, media, categories, authors, and SEO metadata from WordPress to Payload CMS.
Features
- 📝 Post Migration: Migrate WordPress posts with full content preservation
- 🖼️ Media Handling: Automatic image download and upload to Payload media collection
- 🏷️ Categories & Authors: Automatic creation of categories and authors/users
- 🌐 Multi-locale Support: Detect and migrate content in multiple languages (en/vi)
- 🔍 SEO Migration: Preserve SEO metadata from Rank Math and Yoast SEO
- 🎨 Block Conversion: Convert WordPress blocks to Lexical editor or CMS blocks
- 📊 Admin UI: User-friendly interface for migration management
- 🔄 Batch Processing: Process multiple posts in batches
Installation
npm install @teagantb/payload-wordpress-migration
# or
pnpm add @teagantb/payload-wordpress-migration
# or
yarn add @teagantb/payload-wordpress-migrationQuick Start
1. Add Plugin to Config
import { wordpressMigration } from '@teagantb/payload-wordpress-migration'
import { buildConfig } from 'payload'
export default buildConfig({
plugins: [
wordpressMigration({
collections: {
posts: 'posts',
categories: 'categories',
media: 'media',
users: 'users',
},
enableAdminUI: true,
adminRoute: '/migrate-xml',
}),
],
// ... rest of config
})2. Ensure Required Collections Exist
Your Payload config should have these collections:
- posts: With
title,slug,content(richText),category,authors,heroImage,metafields - categories: With
title,slugfields - media: With upload configuration
- users: With auth enabled
3. Use Admin UI
- Start your Payload server:
pnpm dev - Navigate to
/admin/migrate-xmlin your browser - Upload WordPress XML export file
- Configure migration options
- Click "Start Migration"
Configuration Options
interface WordPressMigrationPluginOptions {
/** Block type mappings (WordPress → Payload CMS) */
blockMappings?: {
youtube?: string
video?: string
videopress?: string
gallery?: string
button?: string
media?: string
banner?: string
columns?: string
}
/** Collection name mappings */
collections?: {
posts?: string
categories?: string
media?: string
users?: string
}
/** Enable admin UI (default: true) */
enableAdminUI?: boolean
/** Admin UI route path (default: '/migrate-xml') */
adminRoute?: string
}Programmatic Usage
Migrate from XML File
import { migrate } from '@teagantb/payload-wordpress-migration'
import { getPayload } from 'payload'
import config from '@payload-config'
const payload = await getPayload({ config })
const stats = await migrate(payload, {
xmlFilePath: './wordpress-export.xml',
batchSize: 10,
skipImages: false,
continueOnError: true,
})
console.log(`Migrated ${stats.successfulPosts}/${stats.totalPosts} posts`)Migrate from WordPress API
const stats = await migrate(payload, {
wpApiUrl: 'https://example.com/wp-json/wp/v2',
wpCredentials: {
username: 'user',
password: 'app-password',
},
batchSize: 10,
})Migrate with Mock Data (Testing)
const stats = await migrate(payload, {
useMock: true,
batchSize: 5,
})Migration Options
interface MigrationOptions {
/** Use mock data instead of fetching from WordPress */
useMock?: boolean
/** WordPress API endpoint */
wpApiUrl?: string
/** WordPress API credentials */
wpCredentials?: {
username: string
password: string
}
/** Path to WordPress XML export file */
xmlFilePath?: string
/** XML content as string (Cloudflare Workers compatible) */
xmlContent?: string
/** Batch size for processing posts */
batchSize?: number
/** Dry run (don't actually create posts) */
dryRun?: boolean
/** Skip image uploads */
skipImages?: boolean
/** Continue on errors */
continueOnError?: boolean
}Block Conversion
The plugin automatically converts WordPress blocks:
Lexical-Supported Blocks
- Paragraphs
- Headings
- Lists
- Quotes
- Tables
- Code blocks
CMS Blocks
- Gallery →
galleryBlock - YouTube →
youtubeBlock - Video →
videoBlock - VideoPress →
videopressBlock - Buttons →
buttonBlock - Columns →
columnsBlock
You need to define these blocks in your Payload config. Block slugs can be customized via blockMappings option.
Supported WordPress Features
- ✅ WordPress Block Editor (Gutenberg)
- ✅ Classic Editor HTML
- ✅ Featured Images
- ✅ Categories and Tags
- ✅ Authors
- ✅ SEO Metadata (Rank Math, Yoast SEO)
- ✅ Multi-language (WPML, Polylang detection)
- ✅ Media attachments
Migration Statistics
After migration, you'll receive statistics:
interface MigrationStats {
totalPosts: number
successfulPosts: number
failedPosts: number
totalChunks: number
totalImages: number
totalErrors: number
processingTime: number // milliseconds
}Requirements
- Payload CMS 3.37.0 or higher
- Node.js 18.20.2 or higher
- Required collections: posts, categories, media, users
Development
# Install dependencies
pnpm install
# Run dev environment
pnpm dev
# Build plugin
pnpm build
# Run tests
pnpm testLicense
MIT
Support
For issues and questions, please open an issue on GitHub.
