Payload → WordPress
Read Payload collections with the Local API and create WordPress posts through the REST API. Blocks, access rules, and uploads need a map. There is no official Payload-to-WXR button.
Should you make this move?
Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.
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
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
WordPress: Unmatched ecosystem breadth and content ownership support almost any publishing model. This removes a major source-side concern: There is no one-click importer, so schema, rich text, and media are a scripted project.
What you lose: Open-source collections, blocks, and a Local API keep the content model in code you can host yourself. What you inherit: Plugin, hosting, security, and performance maintenance accumulate over time.
Jump to a section
Know the shape of the move.
This timeline assumes
- You can run a script inside the Payload app, where the Local API can read collections. find is paginated. Pass pagination false when you need every document and you accept the cost.
- WordPress is a fresh site with an application password or a user who can create posts, media, and terms.
- The site already documents Payload → Strapi, and WordPress → Payload in the other direction.
- Gutenberg or the block editor will receive HTML or blocks you generate. Payload blocks do not become PHP blocks.
- Editors stop publishing in Payload during the final copy.
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 |
|---|---|---|---|---|
| Collections | manual | critical | A Payload collection is code. WordPress will not read your config. Posts and pages are the usual targets. Other collections become custom post types only if you register them. | Decide which collections become posts, pages, or a custom type. Skip the rest in writing. |
| Documents | partial | critical | payload.find returns docs plus totalDocs. You create WordPress posts from that list. Store the Payload id in post meta so a second run updates instead of duplicating. | Page through results or disable pagination on purpose. Upsert on the stored id. |
| Blocks and Lexical | partial | critical | Lexical JSON and blocks are not Gutenberg. You render them to HTML or to block markup in the script. | Convert one document per block type first. Keep the raw Payload JSON. |
| Uploads | partial | critical | Upload collections point at files on disk or at an adapter such as S3. WordPress needs those files in the media library. | Upload each file with the media endpoint and rewrite URLs in the post body. |
| Relationships | manual | high | A relationship is a Payload id. WordPress wants a term, a parent, or meta. The id will not match. | Create terms and posts first. Fill relationships after both sides have ids. |
| Localization | manual | high | Localized fields are not WordPress languages. A multilingual plugin has its own model. | Import the default locale first. Add other locales only if the plugin is installed and mapped. |
| Access control | lost | high | Payload access functions are not WordPress roles. Users do not keep sessions. | Create the editors you need and send new passwords. |
| Globals | manual | medium | Header and footer globals are single documents. WordPress menus are a different screen. | Rebuild menus by hand from the global. |
| Versions and drafts | partial | medium | Payload versions are not WordPress revisions unless you create each one. Most moves only take the latest published document. | Import published documents. Leave draft history in the Payload backup. |
| Hooks and custom endpoints | lost | high | Hooks that send mail, resize images, or sync a store do not run inside WordPress. | List hooks that have side effects and replace the ones production needs. |
| Public URLs | partial | critical | Slugs can match. Anything the frontend built from a route that is not the slug will 404. | Crawl the live URLs. Redirect what you cannot recreate. |
Where each thing goes.
| Source | Destination | Method | Notes |
|---|---|---|---|
| Posts collection | WordPress posts | transform | REST POST /wp/v2/posts. Save the Payload id in meta. |
| Pages collection | WordPress pages | transform | Same idea, pages endpoint. |
| Lexical or blocks | post content | transform | Render to HTML or block markup. |
| Upload | Media library | transform | Upload the file, then replace URLs. |
| Category relationship | Category term | transform | Create terms first. |
| Slug | Slug | automatic | Keep it when the URL should not change. |
| User | WordPress user | manual | New password. Map author ids after users exist. |
| Global nav | Menu | manual | Rebuild it. |
| Access functions | No destination | unsupported | Set roles in WordPress. |
Make the move recoverable.
Create the source-of-truth backup
Keep a database dump and an upload archive before WordPress becomes the editor.
- Dump the Payload database.
- Copy the upload directory or the object-storage bucket.
- Record totalDocs per collection.
- Export WordPress once it has a baseline, using Tools, Export, so you can see what the script added.
- Store checksums.
Proof to capture: Dump checksum, upload count, and per-collection totals.
Read every document
Get a complete set despite pagination.
- Call find per collection.
- Either loop pages until you have totalDocs, or set pagination to false and a limit you can afford.
- Write a JSON line per document to a file you can rerun.
- Do not read drafts unless you mean to publish them.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
Create WordPress posts and media
Land content where editors already know how to work.
- Upload media first. Keep a map of Payload file id to WordPress attachment id.
- Create categories and users.
- Create posts and pages with the Payload id in meta. Render body HTML with rewritten image URLs.
- Second pass for anything that points at another post.
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.
Pagination hides documents
find defaults to a page of 10.
- Consequence
- You migrate a sample and call it the site.
- Mitigation
- Compare totalDocs with the number of WordPress posts you created.
Stop if: The counts differ and you have no exception list.
HTML drops a block
A block you do not render becomes nothing.
- Consequence
- Pages lose sections.
- Mitigation
- Convert one of each block before the full run.
Stop if: A sampled page is missing a section.
Both admins stay writable
Editors will keep using Payload if you do not say it is frozen.
- Consequence
- The last edits exist in only one system.
- Mitigation
- Freeze Payload, copy the delta, then send editors to WordPress.
Stop if: A document changed in Payload after the freeze and is not in WordPress.
Do the work in this order.
- Day 1 · inventory
Count collections and blocks
3 hours active1 day elapsedNone waiting- Record totalDocs.
- List blocks and upload collections.
- Dump the database.
Stop / go checkpointIs the scope a content move?
Go when: You know which collections become posts or pages.
Stop when: A collection is really the product catalog and nobody owns that decision.
- Day 2 · wordpress
Prepare WordPress
3 hours active1 day elapsedNone waiting- Install WordPress and the theme you will keep.
- Create an application password.
- Register custom post types you still need.
Depends on: inventory
Stop / go checkpointCan the API create a post?
Go when: A hand-made test post and a test image exist.
Stop when: Auth or permalinks are wrong.
- Days 3 to 5 · import
Import media and documents
1 to 2 days active3 days elapsedUploads waiting- Upload files.
- Create terms, users, posts, and pages.
- Rewrite image URLs.
Depends on: wordpress
Stop / go checkpointDo counts match?
Go when: WordPress counts match totalDocs, with exceptions listed.
Stop when: The gap is unexplained.
- Day 6 · preview
Compare URLs
4 hours active1 day elapsedNone waiting- Request the important URLs.
- Check one page per block type.
- Have an editor edit a post.
Depends on: import
Stop / go checkpointCan editors move?
Go when: The URL sample passes and an editor saved a post.
Stop when: A block or a menu is missing.
- Day 7 · cutover
Freeze Payload and switch
2 hours active1 day elapsedDelta copy waiting- Stop Payload publishes.
- Copy the delta.
- Point the site at WordPress.
Depends on: preview
Stop / go checkpointStay on WordPress?
Go when: The delta is in and the sample still passes.
Stop when: Payload changed after the freeze.
Cut over with a way back.
Cutover
Make WordPress the editor and the public site, with Payload frozen.
- Tell editors Payload is read-only. Record the time.
- Find documents changed after that time and create or update them in WordPress.
- Switch the public host.
- Leave Payload running for the rollback window.
- Send editors their WordPress logins.
Proof to capture: Freeze time, count table, and the URL sample.
Rollback
Point the site back at Payload if WordPress content is incomplete.
- Point the host back at the Payload frontend.
- Do not drop the WordPress database. You may need the delta.
- If editors wrote in WordPress, copy those posts back before they return to Payload.
- Re-open Payload publishing.
- List the URLs that failed.
Proof to capture: Payload serves the public host and WordPress-only edits are listed.
- Counts do not match and the exceptions are incomplete.
- A sampled block is blank.
- Media URLs 404.
- A document changed in Payload after the freeze.
Prove the migration worked.
Every blocking check must pass. Capture the evidence before cleanup begins.
| Pass | ID | Check | Method | Expected result | Evidence |
|---|---|---|---|---|---|
CNT-01Blocking | totalDocs versus WordPress | Compare each collection you intended to move. | Counts match or the exception file names every skip. | The table. | |
PAG-01Blocking | Pagination | Confirm the script logged totalDocs and the number of rows it wrote. | Those numbers match. | The script log. | |
BLK-01Blocking | One page per block | Compare rendered HTML with the Payload admin. | The sections you care about are present. | The page list. | |
MED-01Blocking | Image URLs | Search post content for the old asset host. | Sampled posts point at the WordPress uploads directory. | The search. | |
URL-01Blocking | Slug sample | Request the live paths. | Important URLs return the right post. | Status codes. | |
REL-01Blocking | Categories | Open posts that had relationships. | Terms match. | Two example posts. | |
EDT-01Blocking | A login works | Have an editor edit and update a post. | The update saves. | The post id. | |
FRZ-01Blocking | Freeze | Compare Payload updatedAt with the freeze time. | Later edits are in WordPress. | The timestamp check. |
Remove the scaffolding safely.
Safe after: WordPress has been the public site for a week and editors have published there.
- Keep the Payload dump and the upload archive.
- Revoke the application password if you do not need another delta.
- Leave Payload read-only until the retention date.
- Remove WordPress users created only for the script.
- 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.
- Payload: Local APIAccessed 2026-11-06
- Payload: queries and paginationAccessed 2026-11-06
- WordPress: Tools Export screenAccessed 2026-11-06
- WordPress REST API: postsAccessed 2026-11-06