DEV Community

Hamza Ahmad Aslam
Hamza Ahmad Aslam

Posted on Originally published at hamzaahmadaslam.com

Headless WordPress with Next.js: when it fits

Originally published at hamzaahmadaslam.com.

How this article was made: drafted with AI assistance from a researched brief, then checked against primary documentation before publishing.

Short answer: headless WordPress with Next.js is worth it when you need a very fast, highly custom front end, several channels fed from one CMS, or a team that already works in React. It isn't worth it for a brochure site or a store that leans on page builders and plugins that expect to render the front end. Decide based on content workflow and plugin dependencies, not on hype.

"Headless" means WordPress keeps doing what editors love (writing, media, users, revisions) while a separate application (here, Next.js) renders the pages visitors see. The two talk over an API. It's a powerful setup, but it moves a lot of work from WordPress onto you.

What changes when WordPress goes headless

Area Traditional WordPress Headless WordPress with Next.js
Rendering PHP theme renders every page Next.js renders pages, usually statically with revalidation
Plugins Anything that outputs HTML just works Only data survives; the front end has to be rebuilt
Previews Built in Needs a preview route and draft mode
SEO tags Output by your SEO plugin Fetched from the API and mapped to Next.js metadata
Hosting One server Two systems: WordPress and the front end
Security surface Public WordPress site WordPress can be locked away; the public site is mostly static

The last row is an underrated benefit. When visitors only ever reach the Next.js front end, the WordPress admin can sit behind an allowlist, a VPN or a separate subdomain, which can reduce direct exposure when access restrictions are enforced. A separate hostname alone is not an access control.

When headless WordPress with Next.js is the right call

  • Performance is a product requirement. Statically generated pages served from a CDN are hard to beat on Core Web Vitals, and you control every byte of JavaScript.
  • The design is highly interactive. Complex filters, dashboards, animation or 3D are easier in React than in a PHP theme.
  • One CMS feeds several channels. A website, an app and a kiosk can all read the same content.
  • Your team already ships React. You get type safety, component libraries and modern tooling.

When it's the wrong call

  • The site depends on page builders. Elementor, Divi and similar builders store layouts that only their own PHP can render. Going headless means rebuilding every layout by hand.
  • Plugins render part of the front end. Forms, bookings, memberships and many WooCommerce extensions output their own HTML and scripts. Each one needs an API-based replacement.
  • Editors need true WYSIWYG. Block content can be rendered in Next.js, but matching every core and third-party block takes real effort.
  • The budget is tight. Two systems cost more to build, host and maintain than one well-tuned theme.

If most of these apply, a fast classic theme is usually the better investment.

REST API or WPGraphQL?

WordPress ships with the REST API out of the box. The popular WPGraphQL plugin adds a GraphQL endpoint.

  • REST API: no extra plugin, simple to cache, and many plugins already register their own routes. You may need several requests per page.
  • WPGraphQL: fetch exactly the fields a page needs in one request, with a strongly typed schema. It adds a plugin to keep updated, and some plugins need extensions to expose their data.

For a blog-style site the REST API is often enough. For content models with many relationships, GraphQL usually leads to cleaner front-end code.

A caching strategy that keeps content fresh

The classic mistake is fetching WordPress on every request, which makes the front end as slow as the back end. Instead, render statically and refresh on change:

  1. Fetch content at build time or on first request, and cache it with a tag such as posts.
  2. In WordPress, send a webhook when a post is saved or deleted.
  3. In Next.js, a small route handler verifies a shared secret and calls revalidateTag("posts", "max").
// app/api/revalidate/route.ts
import { revalidateTag } from "next/cache";

export async function POST(request: Request) {
  const secret = process.env.REVALIDATE_SECRET;
  if (!secret || request.headers.get("authorization") !== `Bearer ${secret}`) {
    return new Response("Unauthorized", { status: 401 });
  }
  revalidateTag("posts", "max"); // mark stale; a subsequent request can trigger background refresh
  return Response.json({ revalidated: true });
}
Enter fullscreen mode Exit fullscreen mode

Cached pages remain available while revalidation happens. With the "max" profile, a visitor may receive stale content while a background refresh runs. Keep a time-based revalidation as a safety net in case a webhook is missed.

Previews, SEO and the details people forget

Previews

Editors expect a "Preview" button that works. In Next.js, use Draft Mode on a preview route that checks a secret, then fetch the latest revision with authentication. WordPress Application Passwords are a simple way to authenticate server-to-server requests.

SEO

Your SEO plugin still does the thinking; you just render its output. Yoast SEO, for example, adds a yoast_head_json field to REST responses with the title, description, canonical URL and Open Graph data. Map those fields to Next.js metadata, and generate the sitemap and robots rules in Next.js so they list front-end URLs, not WordPress ones.

Images and links

  • Rewrite image URLs to go through Next.js image optimisation, or serve them from a CDN.
  • Turn internal links inside post content into front-end paths so visitors never land on the WordPress domain.
  • Redirect the old WordPress URLs if the structure changes, to keep existing rankings.

Security checklist for a headless setup

  • Put the WordPress admin on its own subdomain and restrict it (IP allowlist, VPN or an access proxy).
  • Disable what the front end doesn't use: XML-RPC, unused REST routes and user enumeration.
  • Keep secrets (API tokens, revalidation keys) on the server side only.
  • Keep WordPress and plugins updated. Going headless does not remove that need. My WordPress security hardening checklist still applies in full.

How to decide in one afternoon

  1. List every plugin and mark whether it outputs front-end HTML.
  2. List every page template and how it's built (blocks, builder or custom fields).
  3. Estimate the rebuild cost for each front-end feature.
  4. Compare that with what you'd gain in speed, flexibility and security.

If the rebuild list is short and the gains are clear, go headless. If not, invest in the classic stack and revisit later.

For concrete implementations, see headless WordPress examples and their architectures. If you are still deciding, use the free headless WordPress decision aid to weigh the same questions.


Planning a custom WordPress or headless build? Learn about my Custom WordPress Development service or let's talk it through.

Top comments (0)