All posts
Platform migrations

Contentful to Payload CMS Migration

Contentful to Payload migration from a team running Payload in production: collections, blocks, localization, rich text to Lexical and the Next.js setup.

By Mehdi Hassan7 min read

The short answer

A Contentful to Payload migration moves your content from Contentful's hosted platform into Payload, a self-hosted TypeScript CMS that runs inside your Next.js app. You export the space, define collections and blocks in code, convert rich text to Lexical, import through Payload's Local API in dependency order, then validate and switch your queries.

Key takeaways

  • Payload runs inside your Next.js app and stores content in your own Postgres or MongoDB database.
  • Replace Contentful's reference-to-section pattern with Payload's blocks field for page building.
  • Contentful's per-field locales map closely to Payload's field-level localization.
  • Write the import as a script using Payload's Local API, with old IDs stored for repeat runs.
  • You gain ownership and lose a vendor running infrastructure, so plan hosting and backups first.

Part of Headless CMS Migration: How to Move Between Contentful, Sanity, Payload and Strapi

Why move from Contentful to Payload CMS?

Teams move from Contentful to Payload to own their content and stop paying along Contentful's tier boundaries. Payload is open source, self-hosted and lives in the same codebase as a Next.js front end, so content types, locales and editors don't change the license bill.

Our research found that Contentful's tier jumps, such as the 25-content-type ceiling on a smaller space tier noted in Pagepro's write-up, push teams toward Sanity or Payload. Payload is the choice when the team also wants a typed, code-defined schema next to the front end. We run Payload in production on our own site, and this guide reflects that. For the general method, see our headless CMS migration hub, and to compare the hosted alternative, read Contentful to Sanity migration.

Contentful

Payload

Hosting

Vendor-hosted SaaS

Self-hosted, inside your Next.js app

Database

Vendor-managed

Your Postgres or MongoDB

Schema

Defined in the web app or scripts

TypeScript config in your repo

Rich text

Rich text JSON

Lexical JSON by default

Cost shaped by

Spaces, content types, locales, seats

Your hosting, database and storage

How do Contentful concepts map to Payload?

Contentful concepts map to Payload with few gaps: content types become collections, singletons become globals, link fields become relationship fields and assets become an upload collection. The meaningful change is page building, where Payload's blocks field replaces chains of referenced section entries.

Contentful

Payload

Migration note

Content type

Collection

Define fields in TypeScript

Single entry used as settings

Global

Navigation, footer, site settings

Reference to section entries

Blocks field

Inline sections instead of separate entries

Link field

Relationship field

Import referenced docs first

Asset

Upload collection

Re-upload files to your storage

Localized field

Field with localized set to true

Enable locales in the config

Environment

Separate database or deployment

Schema changes move to git

Moving sections into blocks simplifies the model a lot. A landing page that was a page entry with ten references to section entries becomes one document with an array of typed blocks. Editors find it easier, and queries no longer resolve deep link chains. Our guide to content modeling for CMS migrations covers how to make that kind of change deliberately.

How do you run a Contentful to Payload migration step by step?

You run a Contentful to Payload migration by setting up Payload in your Next.js app, defining the schema, exporting from Contentful, transforming the data and importing with a script that uses Payload's Local API. Keep the export as files so you can re-run the transform and import as often as you need.

  1. Set up Payload in your Next.js app

    Add Payload to the app, connect a Postgres or MongoDB database and configure storage for uploads.

  2. Define collections, globals and blocks

    Write the schema in TypeScript, improving on the Contentful model rather than copying it. Turn on localization if you need it.

  3. Export from Contentful

    Use the Contentful CLI's space export to save entries, assets and locales as JSON.

  4. Import media first

    Download every asset and create it in the upload collection, recording a map of Contentful asset IDs to Payload IDs.

  5. Import documents in dependency order

    Create referenced documents such as authors and categories first, then pages and posts, storing the Contentful ID on each.

  6. Patch relationships

    Run a second pass that fills relationship fields using the ID map, so circular references don't fail.

  7. Switch queries and validate

    Replace Contentful API calls with Local API calls in server components, then check counts, references and rendered pages.

How do you convert Contentful rich text to Payload's Lexical format?

You convert Contentful rich text to Payload by mapping each Contentful node to a Lexical node, either directly in a script or by going through HTML with Payload's rich text converters. Direct mapping is more work and keeps embedded entries intact.

Paragraphs, headings, lists, quotes, links and bold or italic marks have clear Lexical equivalents. Embedded assets become upload nodes pointing at your re-uploaded media. Embedded entries, such as a callout box or a code sample, become Lexical blocks you define in the editor config. Inline entry links become internal link nodes with a relationship. For a deeper comparison of HTML, Markdown and structured formats, see migrating rich text between CMSs.

Choosing between the direct and HTML routes

The HTML route renders Contentful rich text to HTML with Contentful's renderer, then converts that HTML to Lexical with Payload's converters. It's quick for plain articles and needs little custom code. Check Payload's current rich text docs for the converters available in your version.

The direct route walks Contentful's JSON tree and builds Lexical JSON node by node. It takes longer to write, but embedded entries and entry links come through as real blocks and relationships instead of markup.

A practical approach is to use the HTML route for posts with no embeds and the direct route for everything else. Scan the export first to see which articles contain embedded nodes.

How do you handle localization when moving to Payload?

You handle localization by enabling Payload's localization config with the same locale codes as Contentful, marking the right fields as localized, and writing each locale's value during import. Contentful and Payload both localize at the field level, so the data shape is close.

In Contentful's export, a localized field is an object keyed by locale code. In Payload, you create the document in the default locale, then update it once per additional locale with that locale's values. Keep locale codes identical so your front-end routes don't change. Decide how fallbacks should work, since Payload can fall back to the default locale when a translation is missing, and match whatever your Contentful setup did. If you're moving localized content from WordPress instead, our WordPress to Sanity or Payload guide covers the plugin-based patterns.

What changes after you leave Contentful for Payload?

After leaving Contentful, you own the infrastructure: database, backups, media storage, upgrades and access control. In return, your schema is typed code in your repo, content reads are local function calls and your bill depends on hosting rather than content types or seats.

Pros

  • No license cost tied to content types, locales or editors
  • Content lives in your database
  • Typed schema reviewed in pull requests
  • Local API reads with no network hop
  • Admin panel lives at a route in your own app

Cons

  • Backups and database upgrades are your job
  • No vendor support desk unless you buy one
  • Editors learn a new admin
  • Fewer marketplace apps than Contentful

Plan editor training and a short period of running both systems. Our notes from production in setting up Payload CMS for a marketing site and CMS setup for marketing websites cover how to give editors page-building freedom in the new admin. If you're moving from another CMS to Payload, see Sanity to Payload and Strapi to Payload.

Frequently asked questions

Do I need Next.js to use Payload?
Payload's current version is built to install into a Next.js app, which is where it fits best. It can also act as a headless API for other front ends, since it exposes REST and GraphQL. If your front end is already Next.js, Payload adds no new service to deploy, which is a large part of its appeal.
Where should I host Payload?
Host Payload wherever your Next.js app runs, with a managed database alongside it. Common choices pair Vercel or another Node-friendly host with managed Postgres or MongoDB, plus object storage for uploads. Pick a database with automated backups, and test a restore before launch, not after the first incident.
Can editors preview content in Payload?
Yes. Payload supports drafts, versions and live preview, so editors can see a page rendered by your front end before publishing. It needs setup in both the Payload config and the front end. Configure it before cutover, because preview is often the feature editors miss most from their old CMS.
How long does a Contentful to Payload migration take?
It depends on content types, rich text complexity, embedded entries, locales and asset volume, plus whether the front end changes too. A clean, single-locale dataset with simple rich text is a much smaller project than a multilingual site with many embed types. Scope from an audit of the Contentful export, not from page count.
Is Payload secure enough for a company website?
Payload gives you access control per collection and field, authentication and the ability to keep the admin on your own domain. Security then depends on how you host and maintain it: patched dependencies, a protected database, secrets management and backups. Treat it like any production app your team owns.

· CEO & Design Director

Copywriter, designer and developer, and founder of Designify Studio. Over five years, 60+ projects across 14+ industries, for startups that have raised $300M+.

Want this done for you? Monthly retainer, $6,000.

Your ongoing design and development team, for products that keep shipping. $6,000, per month, flat fee. Book a free 30-minute call to see if it fits.

Schedule Call