WordPress → Payload
Export WordPress content and media to WXR, model pages, posts, and blocks in Payload, then pull files while WordPress is still online. Themes, plugins, and passwords do not move.
Should you make this move?
Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.
WordPress
- Unmatched ecosystem breadth and content ownership support almost any publishing model
- Editors get a purpose-built publishing workflow instead of raw files
- Plugin, hosting, security, and performance maintenance accumulate over time
- Themes, extensions, and content models add maintenance and portability constraints
Payload
- Open-source collections, blocks, and a Local API keep the content model in code you can host yourself
- Editors get a purpose-built publishing workflow instead of raw files
- There is no one-click importer, so schema, rich text, and media are a scripted project
- Themes, extensions, and content models add maintenance and portability constraints
Payload: Open-source collections, blocks, and a Local API keep the content model in code you can host yourself. This removes a major source-side concern: Plugin, hosting, security, and performance maintenance accumulate over time.
What you lose: Unmatched ecosystem breadth and content ownership support almost any publishing model. What you inherit: There is no one-click importer, so schema, rich text, and media are a scripted project.
Jump to a section
Know the shape of the move.
This timeline assumes
- You can export from Tools, Export, and WordPress stays reachable. Payload's tutorial says the media WXR contains links, so the script fetches files from the live site.
- Payload is a headless CMS you configure in code. Part 2 of the vendor tutorial is the frontend, which you build. It is not a theme import.
- The tutorial maps pages, posts, authors, categories, Gutenberg blocks, media, and menus. ACF and other plugins need their own fields.
- The site already documents WordPress → Strapi, WordPress → Contentful, and WordPress → Sanity.
- Comments, users' passwords, and WooCommerce orders are out of scope unless you add them.
What survives the move.
“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.
| Item | Outcome | Impact | What happens | Mitigation |
|---|---|---|---|---|
| Pages and posts | partial | critical | Payload's part 1 maps pages to a Pages collection and posts to a Posts collection. You create them with a script or by hand. The sample post walks Cover, Paragraph, and Image blocks. | Model those collections first. Store the WordPress post id. Import a sample before the full WXR. |
| Gutenberg blocks | manual | critical | The tutorial parses block markup and rebuilds Payload blocks, plus a React component to render each one. Payload does not run PHP blocks. | List every block in use. Build the ones on real pages. Leave unused blocks out. |
| Media | partial | critical | Tools, Export, Media downloads a WXR of links. The tutorial says the site must stay online so the script can fetch the files into an upload collection. | Run the media script while WordPress answers. Check file sizes. Do not cancel hosting first. |
| Authors and categories | partial | high | The tutorial uses a Users collection for authors and a categories collection for terms. WordPress passwords are not in the WXR. | Create Payload users and send them a new login. Map categories before posts. |
| Menus | manual | medium | The tutorial puts navigation in header and footer globals, not a menu importer. | Rebuild the menus in globals before the frontend cutover. |
| Theme and plugins | lost | critical | Part 2 says you build the frontend. PHP templates, widgets, and plugin tables do not become Payload config. | Treat the theme as a rewrite. Keep WordPress up until the new frontend matches the pages you care about. |
| ACF and custom fields | manual | high | The tutorial calls out posts that use ACF as something you map into collection fields. The core WXR will not invent those fields. | Add a field per ACF key you still render. Skip the rest on purpose. |
| Comments | lost | medium | The published tutorial does not import comments. | Export comments if you must keep them, and tell readers if the new site drops them. |
| Permalinks | partial | critical | WordPress slugs can move into Payload slug fields. The sample gives Home the slug index and says to replace it with an empty string later. | Keep public slugs. Add redirects where you changed them. |
| Users and roles | manual | high | WordPress roles are not Payload access functions. Nobody keeps their password. | Recreate the few people who edit. Set access in config. |
| WooCommerce and other plugin data | lost | high | Orders, subscriptions, and form entries live in plugin tables. A content WXR does not include them. | Leave the shop on WordPress or plan a separate commerce move. The site has WordPress → Shopify if that is the real project. |
Where each thing goes.
| Source | Destination | Method | Notes |
|---|---|---|---|
| WordPress page | Pages collection | transform | Home may need an empty slug, not index. |
| WordPress post | Posts collection | transform | Store the WordPress id. |
| Gutenberg block | Payload block and a React component | manual | The tutorial starts with Cover, Paragraph, and Image. |
| Media WXR | Upload collection | transform | Fetch files from the live site. |
| Category | Categories collection | transform | Import terms before posts. |
| Author | Users collection | manual | No passwords in the export. |
| Menu | Header and footer globals | manual | Rebuild the items. |
| ACF field | Collection field | manual | Only the keys you still render. |
| Theme templates | No destination | unsupported | Part 2 is a new frontend. |
Make the move recoverable.
Create the source-of-truth backup
Keep WXR exports and a database dump before the script writes to Payload.
- Export all content from Tools, Export.
- Export media to its own WXR.
- Dump the database if you have plugin tables you might need later.
- Record post, page, and attachment counts.
- Store checksums.
Proof to capture: Checksums and the three counts.
Model the collections the tutorial names
Have a place for pages, posts, media, users, and categories.
- Create Pages, Posts, Categories, Users, and a Media upload collection.
- Add blocks for the Gutenberg blocks you actually use.
- Add a wordpressId field.
- Create header and footer globals for menus.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
Import media, then posts
Resolve images before body HTML points at them.
- Leave WordPress online.
- Parse the media WXR and upload each file.
- Parse posts and pages. Convert blocks you support. Link authors and categories.
- Write a row to an exception file when a block or a file fails.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
The things most likely to hurt.
These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.
Media links die when WordPress goes offline
The tutorial says the WXR holds links and the script fetches them from WordPress.
- Consequence
- Uploads fail or half the library is empty.
- Mitigation
- Finish media import before you take WordPress down.
Stop if: Any referenced file failed to download.
Blocks render as raw HTML
Unmapped Gutenberg blocks have no Payload component.
- Consequence
- Pages look empty or show markup.
- Mitigation
- Inventory blocks first. Ship components for the ones in use.
Stop if: A top page uses a block you have not mapped.
The theme is treated as data
Part 2 is a new frontend, not an import of PHP.
- Consequence
- You cut over a site that does not match.
- Mitigation
- Compare the templates you still need before DNS or the client switch.
Stop if: A required template has no React block.
Do the work in this order.
- Day 1 · export
Export content and media
2 hours active1 day elapsedNone if the export is small waiting- Export content and media.
- Count posts, pages, and attachments.
- List blocks and plugins that own content.
Stop / go checkpointDo the files open?
Go when: Counts match wp-admin and both WXR files are stored.
Stop when: Media export is missing.
- Days 2 to 4 · model
Collections and blocks
1 to 2 days active3 days elapsedNone waiting- Add the collections and blocks.
- Create the first admin user.
- Decide which ACF keys you will keep.
Depends on: export
Stop / go checkpointIs the model enough for the sample?
Go when: The blocks on the sample pages exist.
Stop when: A top page needs a block you have not named.
- Days 5 to 7 · import
Media, then posts
1 to 2 days active3 days elapsedFile downloads waiting- Upload media from the live site.
- Import categories, authors, posts, and pages.
- Log failed blocks.
Depends on: model
Stop / go checkpointDid the sample import?
Go when: Counts match and failed rows are listed.
Stop when: Media failures are unexplained.
- Days 8 to 10 · frontend
Render the blocks
2 to 4 days active3 days elapsedNone waiting- Build the React blocks from part 2.
- Rebuild menus.
- Compare a set of live URLs.
Depends on: import
Stop / go checkpointDoes the branch match WordPress closely enough?
Go when: The URL sample matches and images are local.
Stop when: A required template is missing.
- Day 11 · cutover
Freeze WordPress and switch
2 hours active1 day elapsedDelta import waiting- Stop publishing.
- Export and import the delta.
- Send readers to the new frontend.
Depends on: frontend
Stop / go checkpointStay on Payload?
Go when: The delta is in and the URL sample still passes.
Stop when: A post went out after the freeze and is not in Payload.
Cut over with a way back.
Cutover
Serve the new frontend from Payload while WordPress is frozen and still online long enough to finish media.
- Set WordPress to stop new publishes. Record the time.
- Export the delta and import it.
- Re-check media on the pages you sampled.
- Switch the public host to the new frontend.
- Leave WordPress running read-only.
Proof to capture: Freeze time, delta counts, and the URL sample.
Rollback
Put readers back on WordPress if pages or media are wrong.
- Point DNS or the proxy back at WordPress.
- Keep the Payload database for the diff.
- Copy any Payload-only edits back into WordPress before editors use the old admin again.
- Re-enable publishing.
- List the URLs that failed.
Proof to capture: WordPress answers the public host and Payload-only edits are written down.
- A sampled URL 404s or shows the wrong blocks.
- Images 404 because WordPress was turned off early.
- A post published after the freeze is missing.
- A required plugin feature has no replacement.
Prove the migration worked.
Every blocking check must pass. Capture the evidence before cleanup begins.
| Pass | ID | Check | Method | Expected result | Evidence |
|---|---|---|---|---|---|
CNT-01Blocking | Post and page counts | Compare WordPress counts with the collections. | Counts match or exceptions are listed. | The count table. | |
MED-01Blocking | Files downloaded | Compare attachment count with the upload collection and spot-check sizes. | No zero-byte files on pages you sampled. | The size check. | |
BLK-01Blocking | Block coverage | List Gutenberg blocks in the WXR and the blocks you render. | Every block that appears on a sampled page has a component. | The block list. | |
URL-01Blocking | Slug sample | Request the old paths against the new frontend. | Each important URL resolves once. | Status codes. | |
AUT-01 | Bylines | Open posts from two authors. | The byline matches WordPress. | The two posts. | |
CAT-01Blocking | Categories | Compare term counts and one archive. | The archive lists the same posts. | The archive URL. | |
PWD-01Blocking | Editors have new logins | Ask an editor to sign in to Payload. | They get in without a WordPress password. | The user id. | |
FRZ-01Blocking | No late posts | Compare WordPress post dates with the freeze. | Later posts are in the delta. | The date check. |
Remove the scaffolding safely.
Safe after: The new frontend has been public for a week and media no longer depends on WordPress.
- Archive the WXR files and the database dump.
- Leave WordPress read-only until the retention date.
- Remove import-only Payload users.
- Turn off WordPress plugins that were only there to help the export.
- Set the next review date.
Verify against the primary material.
Platform behavior changes. Check these sources and the review dates above before executing a production migration.
- WordPress: Tools Export screenAccessed 2026-11-06
- Payload: migrate from WordPress, part 1Accessed 2026-11-06
- Payload: migrate from WordPress, part 2Accessed 2026-11-06
- Payload: Local APIAccessed 2026-11-06