← writing

Headless WordPress without the regret

I built two headless WordPress sites in 2022. One was perfect for the use case. The other was an expensive lesson. Here is how to tell which one you are about to build, before you commit to six months of regret.

I built two headless WordPress sites in 2022. One was perfect for the use case. The other was an expensive lesson. Same stack, same agency tooling, same confident kickoff meeting. Wildly different outcomes.

I want to walk through why, because the difference was not technical skill. It was whether the project was the shape of the tool. Headless WordPress is a real tool with real teeth. It pays you back when you use it for the job it is good at, and it bills you for every hour you spend forcing it to do something else.

When headless WordPress actually earns its keep

There is a small list of project shapes where headless WP is the right call, and I want to name them honestly because the marketing copy around this stack tends to imply the list is much longer than it is.

The first is app-like frontends. If your site is going to behave like a product, with stateful interactions, client-side routing that matters, live data, animations that need to coordinate across pages, you want a real frontend framework owning that experience. WordPress is a good content store for that frontend. The block editor is decent, the role system is mature, the REST and GraphQL surfaces are workable. Letting React or Vue own the visitor experience and letting WP own the editor experience is a sensible split when the visitor experience is genuinely app-shaped.

The second is multiple frontends sharing one content store. A marketing site, a mobile app, and a partner portal that all need to pull from the same articles and product pages. That is exactly the problem headless was invented for. The content lives in one place, the consumers are decoupled, and you do not have three CMSes to keep in sync. This one is real and it is wonderful when it fits.

The third is when the editor experience and the visitor experience are very different. If editors need the full WP admin with all its plugins for workflow, scheduling, multilingual, custom fields, and the visitor needs something that looks nothing like a WordPress theme could ever produce, decoupling is the cleanest answer. The editor gets the familiar tool. The visitor gets the bespoke shell. Neither side compromises.

The fourth is build-time generation across continents. If you have a content catalog that is mostly static, updates a few times a day, and needs to load instantly from Tokyo and São Paulo and Berlin, statically generating pages out of WP and pushing them to a CDN is genuinely fast and genuinely cheap to run. Headless is the path of least resistance for that workflow.

That is the list. Four shapes. If the project I am scoping looks like one of these, headless is on the table.

When it absolutely is not the answer

And here is the list that should give you pause, because it is the list my second 2022 project belonged to and I did not catch it in time.

Small marketing sites that would have been a one-day theme job. A five-page brochure site for a local business. A portfolio. A landing page for a launch. Anything where the content surface is small and the design is the whole point. You can ship that with a tidy WordPress theme in a single day and the client can edit every word of it without help. Going headless turns the same project into a two-week build with a Next.js codebase the client cannot touch, hosting on two platforms instead of one, and a preview story you will spend three afternoons explaining over Slack.

Projects with non-technical editors who want live preview. The WordPress block editor is what those editors know. They click a heading and it looks like a heading. They drop in an image and they see the image. The moment you go headless, that preview either disappears or becomes a brittle approximation that lags behind the real render. Editors will ask why the preview looks different from the site and the honest answer is because there are now two render paths and only one of them is the truth. That conversation does not get easier with time.

Anything where the team does not already maintain a JavaScript app. If your shop is a WordPress shop, the day you go headless is the day you also become a Next.js shop. That is a real second skill set with its own build tooling, its own deployment pipeline, its own dependency upgrade calendar, and its own on-call surface when the static export fails at 2 a.m. If nobody on the team wants that responsibility, do not give it to them.

The gotchas the pitch decks leave out

There are four practical ones I keep running into, and they are worth flagging upfront because each one becomes a project on its own once you commit.

Previews are hard. The Gutenberg block format is JSON that only WordPress knows how to render into HTML. Outside WP, you get a chunk of structured data and you are responsible for turning it back into a page that matches what the editor saw. Some teams solve this by building a parallel block renderer in their frontend. Others use REST endpoints that return rendered HTML and accept that you have lost some of the headless purity. Either way it is real work that nobody quoted for.

Forms and search become the frontend's problem. Contact Form 7 and WPForms do not work the way they used to once the visitor never hits a WordPress page. You either rebuild the form layer on the frontend and post back through REST, or you wire in a third party form service and now you have one more vendor. Same for search. The native WP search is gone the moment you stop rendering WP templates. You will end up reaching for Algolia or Meilisearch or building your own index. Budget for it.

Plugin compatibility breaks in surprising places. A startling number of WordPress plugins assume they are part of the page render. They enqueue scripts, they hook into the_content, they expect to inject markup. The moment the frontend is not a WP theme, those hooks fire into the void. Caching plugins, optimization plugins, popup plugins, cookie banners, analytics injectors. They all have to be replaced or rebuilt on the frontend. None of that work shows up until you are deep in the build.

The two systems tax is real. You are now maintaining two codebases, two deploy pipelines, two sets of dependencies, two security update calendars, two places where breaking changes can land. That is genuinely twice the operational surface, and it does not get smaller over time. Every WordPress upgrade is also a regression test of your frontend's assumptions. Every frontend framework upgrade is a re-check of every page that ever shipped.

The stack worth knowing

WPGraphQL is the GraphQL layer most teams reach for and it is the one I would still pick today. It is mature, it handles custom post types and ACF fields cleanly, and the ecosystem around it is the one with the most working examples on GitHub. Faust.js sits on top of it and gives you a Next.js boilerplate plus a preview shim that takes some of the sting out of the Gutenberg problem. It is not magic but it is the most polished take on this pattern I have used, and if I were starting a headless WP project tomorrow, that is the starting point I would not argue with.

It is also worth knowing about the rise of fake-headless patterns. Server-rendered React inside WordPress itself, where you keep the WP page render but use React components inside the theme. You get most of the developer experience win without paying the two-systems tax. For a lot of projects that is actually the right answer and nobody mentions it because it does not sound as ambitious. It is also less Instagrammable, which I suspect is why we do not hear about it more.

One more time, with feeling

Headless WordPress is a tool. It is a good tool. It is the right tool for app-like sites, for multi-frontend setups, for projects where the editor and the visitor want different things, and for global static catalogs. It is the wrong tool for small marketing sites, for non-technical editors who need a real preview, and for teams that do not already live in a JavaScript app every day.

Use it when the job is the shape of the tool. Walk away when it is not. The regret only ever comes from the second one.

Want more like this?

Occasional, opinionated, no listicles.
all writing →