🇹🇷 Türkçe: Bu yazının Türkçesini oku →
Contentful made headless content management mainstream. It took the idea — stop shipping HTML out of the CMS, give me structured JSON, let my website and app and every other screen pull the same data — and delivered it as a polished cloud service that developers genuinely liked. The idea is correct. The architecture is genuinely better for multi-channel. I am not going to pretend otherwise.
But I have to say the thing that is not fashionable to say, because I have believed it for a long time: most organisations running a headless CMS are feeding exactly one channel — a website. They are paying the full price of the architecture — developer dependency, schema managed as code, a content team that cannot add a field without opening a ticket, a per-API-call and per-seat bill that scales — and receiving almost none of the multi-channel benefit, because there is no multi-channel. There is a website.
When teams realise that, they start looking at WordPress. Here is how I think about the move — plainly first, then technical near the end.
Why teams leave Contentful for WordPress
- The bill versus the benefit. Contentful’s pricing scales with usage, records, and seats. That is worth it when you feed many channels. When you feed one website, you are buying a distribution system to deliver content to your own front door.
- Editorial dependency. In Contentful, the content model is developer territory and the editing experience is deliberately structural. Marketing waits on engineering for changes that, on WordPress, they would just make.
- The whole-stack cost. Headless is not only the CMS bill. It is the custom front-end, its hosting, its CI/CD, and the developers to keep both alive. Collapsing that into WordPress removes an entire layer of cost and coordination.
- Ownership and exit. Contentful is a single well-funded vendor. WordPress cannot be acquired and nobody owns it. For a ten-year content site, that is not nothing.
I wanted headless before it existed — which is exactly why I say this
I am not an outsider throwing stones at headless. I wanted it before it had a name. In 1996 I shipped a university preference assistant on a newspaper-insert CD-ROM, and when a quota changed, the disc was already in a hundred thousand homes with the old number frozen inside it. I wanted content in one place, delivered to whatever screen needed it, updatable without touching the delivery layer. I wanted Contentful thirty years before Contentful existed, and I could not build it because the infrastructure did not exist yet.
So when I tell you to count your channels before you commit to headless, it is not skepticism — it is the opposite. I know precisely how good the architecture is when you need it. Wanting a thing and needing it are different. If you are feeding digital price labels, in-store screens, a mobile app, kiosks, and web from one source, stay on Contentful; it is doing exactly what it is for. If the honest answer is “one website,” the sophisticated architecture is a machine solving a problem you do not have, and moving to WordPress is not a downgrade — it is right-sizing.
How I plan a Contentful migration
Contentful is clean, structured, and has a genuinely good export tool, which makes this one of the more pleasant migrations to execute — the difficulty is in the modelling decisions, not the data wrangling.
- Inventory the content model — every content type, field, reference, the Rich Text fields, assets, and locales.
- Prune the fields and content types that stopped earning their place.
- Map to WordPress — content types to custom post types, fields to ACF, references to relationships, Rich Text to Gutenberg, assets to the media library, locales to your chosen multilingual approach.
- Build the empty target and validate with editors.
- Export, transform, dry-run on staging, repeat.
- Redirects before cutover.
- Cut over, then watch — including the front-end rebuild.
The Technical Part: Where a Contentful Migration Actually Breaks
The specifics that decide the outcome.
The export is clean — use it
Contentful’s contentful space export CLI produces a single JSON file containing every content type, entry, asset reference, and locale, and can download the assets alongside it. This is a genuine gift compared to systems where you have to assemble the content from several APIs. Work from that frozen export, not from live Content Delivery API calls, so your transform is repeatable and safe to fail. Note the distinction between the Content Management API (full data, including drafts) and the Content Delivery API (published only) — decide which state is your source of truth before exporting.
Rich Text is JSON, and that is the real work
Contentful does not store rich text as HTML. It stores it as Rich Text — a structured JSON document (nodeType, content, marks, data) that is conceptually similar to Sanity’s Portable Text but with a different schema. WordPress stores rich text as Gutenberg block markup. Bridging that gap is the core of the migration. You have two honest options:
- Serialize Rich Text to HTML with Contentful’s
rich-text-html-rendererand drop it into a block — fast, but you lose block-native editing. - Map node-by-node to Gutenberg blocks — paragraphs, headings, lists, quotes, and embeds to their
core/*equivalents — more work, correct if editors will keep touching the content.
The part that will bite you regardless is embedded entries and assets inside Rich Text: embedded-entry-block, embedded-asset-block, embedded-entry-inline, and entry-hyperlink nodes point at other Contentful entries and assets. Each needs a handler that resolves the reference to the migrated WordPress equivalent. Inventory every embedded node type before writing the serializer, or those embeds vanish or dump as raw JSON into your published posts.
References and the two-pass problem
Contentful entries reference each other through link fields, by entry ID. Those IDs are meaningless in WordPress, and you cannot resolve them in one pass because the target may not exist yet when you import the source. Two passes: first import every entry and build a map of Contentful entry ID to new WordPress post ID (keep the Contentful ID in post meta); then rewrite every link — reference fields and in-Rich-Text embeds — using that map into ACF relationship fields, post connections, or taxonomy. Watch reference arrays that carry a meaningful order, and preserve it.
Locales
Contentful has first-class localization — locales are built in, and every localized field carries values per locale in the export. Choose the WordPress target — multisite, Polylang, or WPML — before you transform, because splitting Contentful’s per-locale field values into your chosen structure depends entirely on that choice. Handle entries localized in some locales but not others so you do not create orphan translations. The multilingual architecture is decided first; it is an architecture problem, not a translation problem.
Assets
Contentful assets are files with metadata, served from its CDN. Download every asset from the export (or the CDN), re-import into the WordPress media library, and rewrite every reference — both asset-link fields and the embedded-asset-block nodes inside Rich Text. The in-content asset references are the ones that quietly keep pointing at the Contentful CDN and break the day you stop paying for it.
The frontend contract changes — budget for it
This is the largest hidden cost. If a Next.js, Nuxt, Astro, or other front-end consumes Contentful today via the Content Delivery API or GraphQL, that front-end does not survive the migration untouched. It must switch to the WordPress REST API or WPGraphQL, and the response shapes are entirely different — Contentful’s sys/fields/includes structure looks nothing like WordPress’s endpoints. Either rebuild the front-end’s data layer, or retire the custom front-end and use a WordPress theme. Say this out loud in the first meeting; it is the surprise that reshapes the budget.
Environments
Contentful environments (its git-like branching for content) do not have a WordPress equivalent. Migrate from your production/master environment, and fold any environment-based workflow into WordPress’s post statuses plus an editorial plugin if you need it.
My honest closing position
Migrating from Contentful to WordPress is not a retreat from modern architecture. It is a decision, made honestly, that you were running a single-channel website on a multi-channel system and paying for capability you were not using. WordPress right-sizes that: it hands editorial control back to editors, collapses the extra front-end layer, and puts the content on a platform you own outright.
The execution is genuinely pleasant — the export is clean and the model is well-structured. The judgement is in the Rich Text handling, the two-pass references, the locale architecture, and the front-end rebuild. Handle the embedded nodes by hand, resolve references in two passes, decide the multilingual model first, rewrite the asset URLs, and set your redirects before cutover.
I say all of this as someone who wanted headless for thirty years before it existed. That is exactly why I can tell you, without any grudge against the idea: count your channels. If the answer is one, the content belongs somewhere ordinary people can keep it alive without a ticket — and that is the whole job.
One More Thing: But Can’t WordPress Just Do What Contentful Does?
Here is the question I get the moment someone decides to move: if we leave Contentful, do we have to give up the decoupled architecture we actually liked? No. You don’t. And this is where people who still think of WordPress as “just a blog” get a genuine surprise.
WordPress is not new to this. The REST API has shipped in core since late 2016 — nearly a decade of production hardening. WPGraphQL has been around almost as long, and it is now backed by Automattic and on its way to canonical status as WordPress’s GraphQL layer. In other words, the exact thing you pay Contentful for — structured content delivered as JSON to whatever front-end asks — WordPress has been doing, in the open, for years. It did not lose the headless argument. It absorbed it.
So you have two honest paths off Contentful, not one:
- Traditional WordPress — the rest of this article. Give the editors their theme back and let them publish without tickets.
- Headless WordPress — keep the decoupled architecture you liked; just swap the metered SaaS backend for one you own. Content types become custom post types modelled with ACF, Rich Text becomes blocks, and the front-end contract moves from Contentful’s CDA/GraphQL to WPGraphQL (or the REST API) — with your existing Next.js / Nuxt / Astro front-end sitting on top exactly as before.
Model your content with custom post types and ACF, query it with WPGraphQL, and your front-end barely notices the CMS changed underneath it. You keep every advantage of headless. And here is the part that should make you sit up: you gain things a pure headless SaaS never gives you.
- A real commerce engine. WooCommerce. Try bolting a mature store onto a headless-only CMS and watch the custom code and the bill pile up.
- Editorial power for humans, not just developers — a block editor, media library, revisions, roles, and an ecosystem of plugins for SEO, forms, memberships and more, none of which you rebuild from scratch.
- No per-seat pricing, no usage meter. Add a hundred editors or a million API calls; the bill doesn’t move.
- Ownership. The whole argument of this series — nobody can buy WordPress out from under you.
Contentful is genuinely good at what it does — a clean content model, strong first-class localization, a polished cloud. I said so at the top and I meant it. But “we want a decoupled front-end over a structured API” is not a reason to leave WordPress behind — it is a reason to run WordPress headless. You keep the architecture you liked; you just swap the closed, metered backend for an open, ownable one with an ecosystem behind it.
That’s the surprise. You didn’t need to choose between headless and WordPress. You can have both.
Last modified: July 20, 2026
United States / English
Slovensko / Slovenčina
Canada / Français
Türkiye / Türkçe