payload-wordpress-migrator
v0.0.21
Published
A PayloadCMS plugin for WordPress migration - migrate and manage WordPress content directly in your Payload admin dashboard
Maintainers
Readme
Payload WordPress Migrator Plugin
A comprehensive PayloadCMS plugin for WordPress migration - migrate and manage WordPress content directly in your Payload admin dashboard with a powerful React-based interface.
🚀 Features
- 📊 Interactive Migration Dashboard: Real-time progress tracking with a modern React interface
- 🔄 WordPress API Integration: Secure REST API connectivity with application password authentication
- 📋 Smart Job Management: Create, monitor, pause, resume, and retry migration jobs
- 🎯 Content Type Discovery: Automatic detection of posts, pages, media, categories, and custom post types
- 🔗 Advanced Field Mapping: Visual field mapping interface with dot-notation support
- 🖼️ Intelligent Media Migration: Auto-import featured images and content media with duplicate detection
- 🧱 Gutenberg to Lexical: Convert WordPress blocks to PayloadCMS Lexical format
- ⚡ Performance Optimized: Configurable batch processing with background job execution
- 🔄 Resume & Retry: Intelligent job recovery with progress preservation
- 🔒 Production Ready: Comprehensive error handling and SSL certificate management
📦 Installation
# npm
npm install payload-wordpress-migrator
# yarn
yarn add payload-wordpress-migrator
# pnpm
pnpm add payload-wordpress-migrator🚀 Quick Start
Basic Setup
Add the plugin to your Payload config:
import { buildConfig } from 'payload'
import { payloadWordPressMigrator } from 'payload-wordpress-migrator'
export default buildConfig({
// ... your existing config
plugins: [
payloadWordPressMigrator({
wpSiteUrl: process.env.WORDPRESS_API_URL,
wpUsername: process.env.WORDPRESS_USERNAME,
wpPassword: process.env.WORDPRESS_APP_PASSWORD,
collections: {
posts: { wpPostType: 'post', enableBlocks: true },
pages: { wpPostType: 'page', enableBlocks: true },
media: { wpPostType: 'media' },
},
enableMediaDownload: true,
migrationBatchSize: 25,
}),
],
})Environment Variables
Add these to your .env file:
WORDPRESS_API_URL=https://your-wordpress-site.com
WORDPRESS_USERNAME=your-username
WORDPRESS_APP_PASSWORD=your-application-passwordWordPress Setup
Application Password Setup
- In WordPress admin, go to Users → Profile
- Scroll down to Application Passwords
- Enter a name (e.g., "Payload Migration")
- Click Add New Application Password
- Copy the generated password (save it securely)
- Use this password as
WORDPRESS_APP_PASSWORD
REST API Requirements
- WordPress 5.6+ (for Application Passwords)
- REST API enabled (default in most installations)
- User with appropriate permissions for content access
Configuration Options
type PayloadWordPressMigratorConfig = {
// WordPress Connection
wpSiteUrl?: string // WordPress site URL
wpUsername?: string // WordPress username
wpPassword?: string // WordPress application password
// Collection Configuration
collections?: Partial<Record<CollectionSlug, WordPressCollectionMapping>>
// Plugin Control
disabled?: boolean // Disable plugin functionality
disableDashboard?: boolean // Disable dashboard UI
// Performance Settings
migrationBatchSize?: number // Batch size (default: 10)
enableAutoSync?: boolean // Auto-sync on startup
// Media Migration
enableMediaDownload?: boolean // Download actual files (default: false)
maxMediaFileSize?: number // Max file size in bytes (default: 10MB)
allowedMediaTypes?: string[] // Allowed MIME types
allowSelfSignedCerts?: boolean // Allow self-signed SSL (dev only)
}
type WordPressCollectionMapping = {
wpPostType: string // WordPress content type
fieldMapping?: Record<string, string> // Custom field mapping
enableBlocks?: boolean // Convert Gutenberg blocks
customFields?: string[] // ACF field names to migrate
importContentMedia?: boolean // Auto-import content images
}📋 Plugin Architecture
The plugin creates the following collections and components in your PayloadCMS instance:
Collections Added
wordpress-migration: Core collection for managing migration jobs- Job configuration and status tracking
- Progress monitoring with detailed logs
- Built-in dashboard interface
Enhanced Target Collections: Automatically adds WordPress metadata fields to configured collections:
migratedFromWordPress.wpPostId: Original WordPress post IDmigratedFromWordPress.wpPostType: WordPress content typemigratedFromWordPress.migrationDate: Migration timestamp
UI Components
- Migration Dashboard: React-based interface with real-time updates
- WordPress Site Configuration: Secure credential management with localStorage persistence
- Content Type Selector: Dynamic dropdown populated from WordPress API discovery
- Field Mapping Interface: Visual field mapping with source/destination field analysis
- Job Monitor: Live progress tracking with success/failure metrics
API Endpoints
The plugin adds these endpoints to your PayloadCMS API:
POST /api/wordpress/test-connection # Test WordPress connectivity
GET /api/wordpress/migration-summary # Dashboard data with caching
POST /api/wordpress/discover-content # Content type discovery
GET /api/wordpress/migration-jobs # Job status retrieval
POST /api/wordpress/migration-jobs # Start migration jobs
PUT /api/wordpress/migration-jobs # Pause/resume jobs
DELETE /api/wordpress/migration-jobs # Delete jobs
POST /api/wordpress/content-fields # Analyze WordPress fields
GET /api/collections/:slug/fields # Analyze PayloadCMS fields🎯 Content Migration Features
Supported Content Types
| Content Type | Features | Notes | | --------------------- | ------------------------------------------------------- | --------------------------------- | | Posts | ✅ Content, metadata, categories, tags, featured images | Full Gutenberg block conversion | | Pages | ✅ Content, metadata, featured images, custom fields | Hierarchical structure support | | Media | ✅ File downloads, metadata, alt text, captions | MIME type filtering & size limits | | Categories | ✅ Names, descriptions, hierarchy, counts | Taxonomy relationships | | Tags | ✅ Names, descriptions, post associations | Tag cloud support | | Users | ✅ User data, roles, capabilities, avatars | Permission mapping | | Custom Post Types | ✅ Auto-discovery, custom fields, metadata | ACF integration |
Advanced Content Processing
- HTML to Lexical Conversion: Sophisticated converter handles complex HTML structures
- Gutenberg Block Processing: Converts blocks to PayloadCMS block format
- ACF Field Migration: Automatic Advanced Custom Fields detection and migration
- Media Auto-Import: Scans content for WordPress media URLs and imports automatically
- Relationship Preservation: Maintains post-category, post-tag, and other relationships
🖼️ Media Migration
Migration Modes
The plugin supports two modes for media migration:
- Metadata Only (default): Migrates media titles, descriptions, alt text, and URLs
- Full File Migration: Downloads files from WordPress and uploads them to PayloadCMS
Enabling Media File Migration
payloadWordPressMigrator({
enableMediaDownload: true, // Enable file downloads
maxMediaFileSize: 50 * 1024 * 1024, // 50MB limit
allowedMediaTypes: [
'image/jpeg',
'image/png',
'image/gif',
'image/webp',
'application/pdf',
'video/mp4',
],
allowSelfSignedCerts: true, // For development only
})Auto-Import Features
Featured Image Auto-Import
- Automatically detects and imports featured images using WordPress
_embeddata - Fallback support when
_embeddata is unavailable - Creates PayloadCMS media records with actual file downloads
- Links imported media to posts/pages via
featuredImagefield
Content Media Auto-Import
- Scans HTML content for WordPress media URLs (
wp-content/uploads) - Downloads and imports images referenced in post/page content
- Preserves alt text and title attributes
- Smart duplicate detection to avoid re-importing existing files
MediaBlock Conversion
When migrating content with enableMediaDownload: true, the plugin now converts HTML <img> tags to proper PayloadCMS MediaBlocks:
- HTML Images → MediaBlocks: Converts inline images to structured MediaBlock components
- Media Import Integration: Automatically downloads and links media files to MediaBlocks
- Rich Editor Support: MediaBlocks display properly in PayloadCMS Lexical editor
- Frontend Rendering: Works seamlessly with PayloadCMS RichText component
- Metadata Preservation: Maintains alt text, titles, and dimensions for accessibility
Configuration Example
collections: {
posts: {
wpPostType: 'post',
importContentMedia: true, // Enable content media auto-import
},
media: {
wpPostType: 'media' // Required for media storage
}
},
enableMediaDownload: true // Required for auto-importMigration Workflow Options
- Recommended: Migrate posts/pages only - media will be auto-imported
- Alternative: Migrate media first, then posts/pages (avoids duplicates)
Performance Considerations
- Files processed in configurable batches to prevent memory issues
- Large files streamed to minimize memory usage
- Failed downloads don't stop the entire migration process
- Media auto-import runs in parallel for optimal performance
- Smart duplicate detection prevents re-importing existing media
🔧 Advanced Configuration
Complete Configuration Example
import { buildConfig } from 'payload'
import { payloadWordPressMigrator } from 'payload-wordpress-migrator'
export default buildConfig({
plugins: [
payloadWordPressMigrator({
// WordPress Connection
wpSiteUrl: process.env.WORDPRESS_API_URL,
wpUsername: process.env.WORDPRESS_USERNAME,
wpPassword: process.env.WORDPRESS_APP_PASSWORD,
// Collection Configuration
collections: {
posts: {
wpPostType: 'post',
enableBlocks: true,
importContentMedia: true,
customFields: ['_yoast_wpseo_title', '_yoast_wpseo_metadesc'],
fieldMapping: {
'title.rendered': 'title',
'content.rendered': 'content',
'excerpt.rendered': 'excerpt',
},
},
pages: {
wpPostType: 'page',
enableBlocks: true,
importContentMedia: true,
disableHtmlConversion: false, // Enable HTML to Lexical conversion
},
media: {
wpPostType: 'media',
},
categories: {
wpPostType: 'category',
},
products: {
// Custom post type example
wpPostType: 'product',
enableBlocks: false,
customFields: ['_price', '_stock_status', '_featured'],
},
},
// Performance & Batch Settings
migrationBatchSize: 25,
enableAutoSync: false,
// Media Configuration
enableMediaDownload: true,
maxMediaFileSize: 50 * 1024 * 1024, // 50MB
allowedMediaTypes: [
'image/jpeg',
'image/png',
'image/gif',
'image/webp',
'image/svg+xml',
'application/pdf',
'video/mp4',
'video/webm',
'audio/mpeg',
],
// Development Settings
allowSelfSignedCerts: process.env.NODE_ENV === 'development',
// Plugin Control
disabled: false,
disableDashboard: false,
}),
],
})Field Mapping Configuration
The plugin supports sophisticated field mapping with dot notation:
fieldMapping: {
// WordPress field path → PayloadCMS field path
'title.rendered': 'title',
'content.rendered': 'content',
'meta._yoast_wpseo_title': 'seo.title',
'acf.hero_image': 'hero.image',
'custom_field_name': 'mappedField'
}🎛️ Migration Dashboard
The plugin provides a comprehensive React-based dashboard accessible at /admin/collections/wordpress-migration:
Dashboard Features
- Site Configuration: Secure WordPress credentials management
- Content Discovery: Automatic scan and analysis of available content
- Job Creation: Visual job setup with field mapping interface
- Real-time Monitoring: Live progress updates with success/failure metrics
- Job Controls: Start, pause, resume, retry operations
- Error Reporting: Detailed logs and error analysis
Dashboard Screenshots
The interface includes:
- Configuration Panel: WordPress site setup and testing
- Content Overview: Discovered content types with item counts
- Job Management: Active and completed migration jobs
- Progress Tracking: Visual progress bars with detailed statistics
- Log Viewer: Real-time migration logs and error reporting
🛠️ Development & Extension
Plugin Structure
src/
├── components/ # React UI components
│ ├── MigrationDashboardClient.tsx # Main dashboard
│ ├── ContentTypeSelect.tsx # Content type picker
│ ├── FieldMappingConfiguration.tsx # Field mapper
│ └── SimpleFieldMapping.tsx # Simple mapping UI
├── utils/
│ ├── wordpressApi.ts # WordPress API client
│ └── htmlToLexicalConverter.ts # Content conversion
└── index.ts # Plugin entry pointCustom Field Transformations
Extend the plugin with custom field transformations:
// In your plugin configuration
const customTransform = (wpItem: any, contentType: string) => {
// Custom transformation logic
return transformedData
}Error Handling
The plugin provides comprehensive error handling:
- Connection Errors: WordPress API connectivity issues
- Authentication Errors: Invalid credentials or permissions
- Content Errors: Malformed content or missing fields
- Media Errors: Download failures or file size limits
- Database Errors: PayloadCMS creation failures
📊 Migration Best Practices
Pre-Migration Checklist
✅ WordPress Setup
- Generate application password
- Verify REST API access
- Check user permissions
- Test SSL certificate
✅ PayloadCMS Configuration
- Configure target collections
- Set up field mappings
- Test media collection setup
- Verify storage configuration
✅ Content Analysis
- Run content discovery scan
- Review field mapping options
- Identify custom post types
- Plan migration sequence
Migration Strategy
Recommended Migration Order:
- Categories & Tags (establishes taxonomy)
- Media Files (creates media library)
- Pages (static content first)
- Posts (blog content with relationships)
- Users (author information)
- Custom Post Types (specialized content)
Performance Optimization:
- Start with smaller batch sizes (10-25) for initial testing
- Increase batch size (50-100) for production migrations
- Monitor memory usage during large media migrations
- Use resume functionality for interrupted migrations
Troubleshooting Common Issues
Collection Configuration Required
Error: "The following path cannot be queried: migratedFromWordPress"
Solution: Ensure all target collections are configured in plugin options:
collections: {
posts: { wpPostType: 'post' },
pages: { wpPostType: 'page' },
media: { wpPostType: 'media' }, // Required for media migration
}Media Migration Issues
Error: "MIME type not allowed" or "File too large"
Solution: Adjust media configuration:
allowedMediaTypes: ['image/jpeg', 'image/png', /* add more types */],
maxMediaFileSize: 50 * 1024 * 1024, // Increase size limitSSL Certificate Errors
Error: "self-signed certificate" in development
Solution: Enable self-signed certificates for development:
allowSelfSignedCerts: process.env.NODE_ENV === 'development'🔧 Technical Requirements
- Node.js: ^18.20.2 || >=20.9.0
- PayloadCMS: ^3.29.0
- Package Manager: pnpm ^9 || ^10
- WordPress: 5.6+ with REST API enabled
- Memory: 512MB+ recommended for media migrations
- Storage: Adequate space for media file imports
📈 Performance Considerations
- Batch Processing: Configurable batch sizes prevent memory overflow
- Background Jobs: Non-blocking migration execution
- Progress Persistence: Resume interrupted migrations
- Memory Management: Efficient file streaming for large media
- Cache Management: Intelligent caching with invalidation
- Parallel Processing: Concurrent media imports for optimal speed
🤝 Contributing
We welcome contributions! Areas for enhancement:
- Additional content type support
- Enhanced field mapping UI
- Performance optimizations
- Advanced content transformations
- Integration tests
- Documentation improvements
📝 License
MIT License - see LICENSE file for details.
🎯 Roadmap
- [ ] WordPress multisite support
- [ ] Advanced Custom Fields Pro support
- [ ] WooCommerce product migration
- [ ] Automated testing suite
- [ ] Docker development environment
- [ ] Migration templates and presets
- [ ] Webhook integration for real-time sync
Author: Igor Abdulovic at Brightscout
Repository: GitHub
Issues: GitHub Issues
