← Writing  ·  Tutorials · WordPress · Headless

Headless WordPress with Next.js and WPGraphQL.

When headless makes sense, when it does not, and the exact wiring I use to ship a fast, editor-friendly headless build.

S
Saugat Rimal
Frontend Developer · May 05, 2023
11 min read Headless WordPress Next.js
WP+

“Headless WordPress” used to mean a research project. In 2026 it is just one more way to ship a WP site — but it is not always the right one. Here is how I decide, and the exact wiring I use when the answer is yes.

01When headless makes sense

  • You need top-of-the-line performance and the client has a complex Gutenberg-style editor experience they do not want to give up.
  • You are building a marketing site that integrates with a React app elsewhere and want one frontend stack.
  • You have an existing WP install with years of content and do not want to migrate the CMS — just modernize the frontend.
  • You want preview, scheduling, and authoring workflows that no headless CMS does as well as WordPress.

02When it absolutely does not

  • Tiny brochure sites. Classic WP is faster to ship.
  • Clients who insist on a page-builder plugin (Elementor, Divi). Those do not translate to headless cleanly.
  • You have no Node deployment story. Adding Vercel/Netlify-flavored devops to a team that only knows cPanel is a tax.
Headless WP doubles your surface area: two stacks, two deploy targets, two security postures. If you cannot articulate why, default to classic WP.

03The stack I use

  • WordPress + ACF Pro as the CMS.
  • WPGraphQL + WPGraphQL for ACF as the API layer.
  • Next.js 15 (App Router) as the frontend.
  • TypeScript + GraphQL Codegen for typed queries.
  • Vercel for deploy with ISR.

04The WordPress side

Required plugins: wpgraphql, wpgraphql-acf, wp-graphql-jwt-authentication (for previews), and advanced-custom-fields-pro (you already have this).

Expose your ACF fields under “Show in GraphQL” on each field group. That is it on the CMS side — your existing theme can stay (you will keep it for the WP-admin UI even though it does not render the frontend).

05The Next.js side

A typical page fetch:

// app/[slug]/page.tsx
import { getPage } from "~/lib/wp";

export default async function Page({ params }: { params: { slug: string } }) {
  const page = await getPage(params.slug);
  if (!page) notFound();

  return (
    <article>
      <h1>{page.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: page.content }} />
    </article>
  );
}

export const revalidate = 60; // ISR: re-fetch at most every 60s

Keep the data layer thin: one helper file (lib/wp.ts) with the GraphQL queries and typed return values. Generate types with GraphQL Codegen so you never guess what a field returns.

06Editor previews

The hardest part of headless WP is making previews work. The editor saves a draft and expects to see it on the frontend.

The pattern: a Next.js preview route that takes a JWT, sets a preview cookie, and renders the page with draft data instead of publish data. Wire it up properly and editors do not notice they are on a headless stack.

07Lessons from real projects

  • Cache aggressively. Use ISR or on-demand revalidation. Do not hit WordPress on every request.
  • Image optimization is your job now. WP’s built-in image sizes do not help. Use Next.js <Image> or Cloudinary.
  • Auth is your job. If you need gated content, you are not getting WP’s cookie auth for free.
  • Document the deploy. Two stacks means two times the README. Do not skip this.

Headless WP is not magic. It is a deliberate trade — performance and frontend flexibility in exchange for ops complexity. When it fits, it really fits.

Headless WordPress Next.js WPGraphQL JAMstack Performance