Headless WordPress Content Platform
Decoupling a content-heavy WordPress site from its frontend, without losing the editorial workflows the content team relied on.
This case study describes a representative engagement drawn from my work on headless WordPress migrations — details are generalized rather than tied to a specific client under NDA.
Overview #
A publishing-focused WordPress site needed significantly better frontend performance and more flexibility in how content was presented, without disrupting the editorial team's existing WordPress workflow. The result was a decoupled architecture: WordPress stayed as the content management system and API, with a separately deployed frontend consuming it.
The Problem #
The existing setup coupled content, presentation, and a large plugin ecosystem into a single monolithic WordPress theme. That made:
- Frontend performance hard to improve without touching plugin-rendered markup
- Design changes slow, since every layout change required PHP template work
- Content reuse across multiple surfaces (site, newsletter, partner syndication) difficult, since content only existed as rendered HTML
The Solution #
Rather than a full "headless from scratch" rebuild, the migration was scoped deliberately:
- Audited every plugin that rendered its own markup directly into the page (SEO, related-posts, forms) to determine which needed a headless-compatible replacement versus which could stay server-side behind the API.
- Built a custom REST namespace (
site/v1) that returned exactly the fields the frontend needed, rather than the default chattywp/v2response shape — keeping the API cacheable and intentional. - Wired preview support using signed tokens so editors could preview unpublished drafts on the new frontend, matching the preview experience they were used to.
- Added webhook-based revalidation — WordPress notifies the frontend on publish/ update, triggering on-demand static regeneration instead of relying on a fixed cache TTL.
add_action( 'rest_api_init', function () {
register_rest_route( 'site/v1', '/posts/(?P<slug>[a-z0-9-]+)', [
'methods' => 'GET',
'callback' => 'site_get_post_by_slug',
'permission_callback' => '__return_true',
] );
} );Technology Stack #
WordPress remained the CMS and content API. The new frontend was built with Next.js, consuming WordPress's REST API through a custom namespace. Docker kept local, staging, and production environments consistent for both the WordPress backend and the frontend build pipeline.
Lessons Learned #
The riskiest part of a headless migration isn't the frontend — it's every plugin that
silently assumed a WordPress-rendered page existed. Auditing that dependency graph
before writing frontend code avoided a mid-project scramble to replace an SEO plugin
that turned out to only work via wp_head().