Web Tech & WebOps 9 min read

WordPress as a Headless CMS: A Field Report

WordPress stays, but no longer serves a single page. Instead, Astro builds 1,380 static HTML files from its content, in 46 seconds. Why we built a project this way, which traps hide in the REST API, why the deploy needed two safety rails, and why WordPress as an editorial system is getting more interesting right now, not less.

Simon Bluhm
Co-Founder, rulers · LinkedIn ↗
Web Tech · Field Report
WordPress Static
TL;DR

WordPress stays as the editorial system behind password protection; visitors only get static HTML from an Astro build: 1,380 pages in 46 seconds, built on GitHub, rsynced to the webspace. Result: fast, practically unassailable, no cookies, no consent banner, and a WordPress update can no longer damage the public site. The lessons: the REST API omits data silently, a deploy needs safety rails against half-finished builds, and verification happens in a real browser, not in an HTML diff. Plus the look ahead: with the Abilities API and the MCP adapter, WordPress as a pure backend is only now getting really interesting.

The core idea

WordPress stays, but only as the editorial system. It no longer serves a single page to visitors. Instead, a build process fetches all content through the API and generates finished HTML files that sit on the webspace. A visitor gets pure files: no PHP, no database query, no attack surface.

The trigger was concrete, not architectural idealism: the old site depended on a custom editor component built by the previous agency. When WordPress evolved, it broke, and the editorial team suddenly found themselves writing raw HTML into the forms. A system that can break with every update was not something we wanted to build again.

The backend: lean instead of a plugin zoo

The editorial environment runs under its own address behind password protection. Deliberately little lives inside:

  • The purchased theme as the base, a small child theme on top. The child theme switches off exactly the three things that caused the old trouble and keeps everything useful: the 38 page templates, the image crops, the styling of the editing forms.
  • Five own mini plugins, each with exactly one job: restrict the editor to core blocks (so no update can wreck anything again), provide the endpoints for the frontend, trigger the rebuild after every save, tidy the magazine section, enable the preview.
  • The data model in ACF: 18 content types, around 230 published posts, 32 pages. Apart from ACF there are no third-party plugins left.

That is half of the security story: every plugin that is not installed can neither break nor be hacked.

The API and its silent gaps

The frontend reads via the WordPress REST API, extended by own endpoints for site settings and menus. Plus custom fields for things WordPress does not expose cleanly: the featured image (WordPress refuses images that were once uploaded inside a draft), the image credits, the downloads and the inline images.

This is exactly where most of the project's bugs lived, and it is the most important warning for anyone following this path: the REST API appears to deliver everything, but in edge cases it omits data without complaint. No error code, no hint, just an empty field. If you build headless, you need frontend-side checks that make missing required data loud instead of silently building empty pages.

The frontend: Astro and search in the browser

The frontend is built with Astro, currently the fastest-growing framework for this kind of project because it ships zero JavaScript by default. Every theme template of the old site was rebuilt as a component with the same markup and the same classes, because the stylesheets depend on them. The stylesheets were taken over unchanged; the behavior (menu, pagination, gallery, downloads) was rewritten without the old site's heavyweight animation library.

One build run fetches all content and generates 1,380 pages in about 46 seconds, including 813 pages of legacy archive from the previous system, carried along as files. A static site has no server that could answer search queries, so search runs the other way around: the build generates an index file of roughly 850 KB from all content, about the size of a single photo. On the first keystroke in the search field, the browser loads this file once and then searches it locally via JavaScript, with results in milliseconds. The side effect is a genuine advantage: no search term ever leaves the device, no search service and no consent needed. The limit is foreseeable but far away: the index grows with the content, and only at a multiple of today's page count would you switch to an external search service.

The plugin route: headless without custom code

Not every project needs custom endpoints and a tailor-made build. There is an established toolbox for getting started:

  • WPGraphQL turns WordPress into a GraphQL API, including a built-in query IDE for testing. The practical advantage over REST: you explicitly request the fields you need, which makes it easier to notice when one stays empty. Its ecosystem (Apollo, Next.js, Gatsby) is the largest in the headless WordPress space.
  • Faust.js, WP Engine's official framework, ships ready-made solutions for the two hardest nuts: authentication and the editorial preview, for which we built our one-time-key build.
  • CoCart adds cart endpoints to WooCommerce if a shop is going headless.
  • Static export plugins like Simply Static generate HTML files straight out of WordPress, with no custom frontend at all. The cheapest entry into static delivery, though with the old theme and all its baggage.

A warning with a current occasion: older tutorials (including the much-linked Hostinger one) still recommend Frontity. Its development stopped years ago, the team moved to Automattic. Building on it today means building on abandoned ground, and exactly that kind of dependency was the reason for our project in the first place. The contemporary alternative is an actively maintained, lightweight framework like Astro or Next.js, which is exactly the setup from this report. We build such frontends completely ourselves as an agency: data model, APIs, build pipeline and operations.

Our take: the plugin route lowers the entry cost considerably and is enough for many projects. We chose the custom build because three requirements broke it: the pixel-perfect rebuild of the 38 existing templates, the preview with exactly the same templates, and the nightly recalculation of expiring events. If you do not have those special cases, WPGraphQL plus Faust.js or a static export gets you there faster and cheaper.

Building and publishing

Builds run on GitHub, not on the webspace. Four triggers: saving in the backend, a nightly run, a manual button, and every change to the source code. The result goes to the webspace via rsync. Two safety rails proved necessary, both learned through pain:

  • A minimum page count. A network error during the build can produce a half-finished but formally successful build. Without the lower bound, exactly such a build would once have emptied the website.
  • Rules for what cleanup must leave in place. This is where the legacy archive was served without any styling for weeks, because the sync had disposed of its assets as "no longer needed".

The nightly run is not a luxury: the old site checked on every request whether an event had passed. A static site only knows the state of its last build, so it has to recalculate once a day. That is the core pattern of headless: everything that used to happen at request time needs a new home.

The preview question

Editorial teams need a preview, and with static sites that is the conceptually hardest nut. Our solution: the preview button in the editor generates a secret one-time key and triggers a dedicated build. It fetches the draft via that key, builds it with the same templates as everything else, and places just that one page under an unguessable address. A separate preview view would be the wrong path: sooner or later it would look different from the website, and then it would be worthless.

Verifying in a real browser

The part we had underestimated and that delivered the most. After two rounds of rejections from the client, we stopped comparing HTML and have since verified in a real browser: screenshots of both sites side by side, measured spacings and widths, buttons actually clicked. Plus an acceptance list of by now 46 checks that proves every reported correction against the delivered file.

The insight behind it applies far beyond this project: most bugs were not visible in the HTML at all. They only emerged from the interplay of CSS, fonts and JavaScript, or the testing tool itself silently tested nothing. If you only diff source code, you are testing the blueprints, not the house. We verify our own website and every tracking setup by the same principle: in the rendered browser, not in theory.

The balance: gains and limits

The site is fast and practically unassailable because no program runs on the web server. It loads nothing from third-party servers, sets no cookies and therefore needs no consent banner. A WordPress update can no longer damage the public site; worst case the backend stalls while the website keeps running. The editorial team keeps its familiar interface.

The limits belong on the table too: everything that normally happens at request time has to be solved differently. Expiring events via the nightly run, search in the browser, previews via a dedicated build. Changes are not visible instantly but after one to two minutes. And the setup costs more development time up front than a classic theme; headless pays off when stability, security and speed matter more over the years than the cheapest start. For a five-page company site it would be overkill, and we say so. How we weigh such decisions is on our Web Tech & WebOps page; we build projects like this as custom development.

Where WordPress is heading

You might think that reducing WordPress to the editorial role is a bet against WordPress. The opposite is currently true. Since 2025, the dedicated WordPress AI team has been building official AI building blocks, and the direction strengthens exactly the backend scenario:

  • Abilities API (in core since WordPress 6.9): a site's functions are registered as typed, discoverable "abilities" with input and output schemas and permission checks.
  • Official MCP adapter (since February 2026): it connects those abilities to the Model Context Protocol, so AI assistants like Claude or ChatGPT can create content and execute tasks through a standard instead of one-off integrations.
  • Roadmap to 7.2 (December 2026): reusable site context for AI features and embedding support for semantic search over your own content.

For headless setups this means: the editorial system, which only manages content anyway, becomes the clean docking point for AI tools, while the delivered website remains completely untouched. And adoption is picking up: according to an analysis by hosting provider HostPress, around 8 percent of WordPress installations already run headless. AI-assisted editing in the backend, static HTML without a single third-party script in the frontend: that separation is getting more valuable, not less. If you need runtime interactivity (shops, portals, personalization), classic or hybrid WordPress remains the right call; the market is visibly sorting itself into exactly these camps in 2026.

If you are facing the question of whether your WordPress site needs a rebuild, a headless migration or just a thorough cleanup: we have been building and running websites as an agency since 2010, and in the intro call we will tell you honestly which of the three paths fits your budget and team. On request we handle the implementation end to end, from data model through build pipeline to browser-based acceptance.

FAQ

Why keep WordPress if the site becomes static?

Because the editorial team knows it and the data model lives there. Headless only swaps the delivery, not the editing interface. And with the Abilities API and MCP, the backend is becoming AI-capable right now.

Can a WordPress update still break the website?

Not the public site. Worst case, the backend stalls; the static files keep running.

How fast are changes live?

One to two minutes after saving. Too slow for minute-by-minute news, irrelevant for most sites.

Does the site still need a cookie banner?

Not in this setup: no third-party servers, no cookies, search runs locally in the browser. Only with analytics or embeds do the usual consent rules return.

← All posts Web tech at rulers →