Headless WordPress

Connecting Next.js to WordPress: A Setup Guide

How to wire a Next.js frontend to WordPress: rendering strategy, routing, data fetching, revalidation, images and the pieces that are easy to forget.

By 6 min read
WordPress admin panel connected by an API to a separate frontend app

Putting Next.js in front of WordPress is a well-trodden path now, and the basic version — fetch posts, render them — takes an afternoon. What takes longer is everything a WordPress theme gave you for free and now has to be rebuilt.

Here's how I set one up, and the order the decisions come in.

Decide the rendering strategy first

This is the decision everything else follows from, and changing it later means reworking the data layer.

  • Static generation: pages are built at deploy time and served as files. Fastest possible, cheapest to host, and the content is only as fresh as the last build unless you add revalidation.
  • Static with incremental revalidation: pages are static but regenerate on a timer, or on demand when WordPress tells the frontend something changed. This is the sweet spot for most content sites.
  • Server rendering: every request renders on the server, hitting WordPress each time. Always fresh, and you now need WordPress to be fast and available for every visitor — which loses much of the point.
  • Client-side fetching: the page shell loads, then JavaScript fetches content. Worst for SEO and perceived speed; use it only for genuinely dynamic, personalised sections.
  • For a marketing site or a blog, static with on-demand revalidation is almost always right.

Set up WordPress as a backend

  • Put WordPress on its own subdomain or a separate host, and keep the admin off the public frontend domain. That's part of the security benefit of going headless.
  • Register custom post types and taxonomies with show_in_rest so they exist in the API at all.
  • Expose the custom fields the frontend needs — register_post_meta with show_in_rest, or the relevant bridge for your field plugin.
  • Decide what the frontend needs and build endpoints for it, rather than making three generic requests and discarding most of each response.
  • Configure CORS if the browser will call WordPress directly. If all fetching happens server-side at build time, you don't need to.
  • Lock down what shouldn't be public — the users endpoint in particular.

Routing and URL parity

Your Next.js routes have to match the URLs WordPress was serving, or you've quietly done a site migration without redirects.

Map each WordPress URL pattern to a dynamic route: posts, pages, category archives, tag archives, author pages, pagination. Generate the static paths from the API at build time.

Nested pages are the common trap. WordPress pages can be hierarchical with multi-segment paths, which needs a catch-all route rather than a single dynamic segment.

Handle the 404 case deliberately — a path that doesn't exist in WordPress must return a real 404 status, not a 200 with a 'not found' message. Soft 404s confuse search engines and hide broken links.

Keeping content fresh

A fully static site shows yesterday's content until the next deploy, which editors find unacceptable within about a day.

On-demand revalidation solves it: WordPress calls a webhook on your frontend when a post is saved, and the frontend regenerates just that page plus the listings it appears on. The editor publishes and sees the change in seconds.

Implement it carefully. Protect the revalidation endpoint with a secret — an open one is a way for anyone to hammer your build. Revalidate the specific paths affected, not the whole site. And have a time-based fallback so a missed webhook doesn't freeze a page indefinitely.

Previews

This is the feature editors miss most, and the one most likely to be descoped and then urgently requested after launch.

In a traditional theme, preview just works. In a headless setup, the draft doesn't exist publicly, so the frontend has to request it authenticated, and it has to render it without caching it.

The mechanism is: a preview link from WordPress carrying a token, a route on the frontend that validates the token and enters preview mode, and data fetching that uses authenticated requests and bypasses the static cache while in that mode. Budget real time for it.

Images

WordPress generates multiple sizes and a srcset; Next.js has its own image component with its own optimisation pipeline. You need to decide which one is doing the work, because doing both is wasteful and doing neither is slow.

Using the Next.js image component means configuring your WordPress domain as an allowed source, and it means images are optimised at your frontend's edge. Using WordPress's sizes means passing the srcset through and letting the browser choose.

Either way, carry the dimensions through from the API so the frontend can reserve space and avoid layout shift, and make sure alt text comes across — it lives in WordPress's media metadata and is easy to drop.

The pieces people forget

  • Forms. WordPress form plugins output HTML and JavaScript that no longer exists. You need a form on the frontend posting to an endpoint — WordPress, or a separate service.
  • Search. WordPress's built-in search is a theme feature. You'll query the API's search parameter or use a dedicated search service.
  • Menus. Not in the core REST API by default; you'll need a plugin or a custom endpoint to expose them.
  • Sitemaps and robots.txt. WordPress generates these for its own URLs, which are now the wrong domain. Generate them from the frontend.
  • Redirects. Any redirect plugin's rules live in WordPress and must be replicated or fetched by the frontend.
  • SEO metadata. Titles, descriptions, canonicals, Open Graph tags and schema all have to be rendered by the frontend from data the API provides.
  • Comments, if you use them.

Deployment and environments

You now have two applications to deploy and two sets of environment variables. Keep the WordPress API URL and any credentials in environment configuration rather than hard-coded, and make sure staging points at staging.

Think about what happens when WordPress is down. With static generation, the site keeps serving — which is a real resilience benefit. With server rendering, the site goes down with it. Add error handling and fallbacks either way, because a failed build caused by a WordPress hiccup is a deploy you can't do.

Cache API responses at build time where you can, so a slow WordPress doesn't make every build slow.

Is it worth it?

For a site that's already React, or one that needs to feed several frontends, or one where the CMS genuinely must be off the public domain — yes, clearly.

For a marketing site that a WordPress theme would serve perfectly well, you're taking on a second application, a rebuild of everything plugins did on the frontend, and a preview implementation, in exchange for speed you could largely get with good caching.

Make that decision with the full list above in front of you rather than after the first afternoon, when fetching posts and rendering them felt easy.

Frequently asked questions

Should I use static generation or server rendering with WordPress?

Static generation with on-demand revalidation for almost all content sites. It gives you the speed of static files plus updates within seconds of an editor publishing, and the site keeps serving even if WordPress is down. Server rendering makes WordPress a dependency of every page view, which loses much of the benefit.

How do editors preview drafts in headless WordPress?

It has to be built. A preview link from WordPress carries a token; a route on the frontend validates it, enters preview mode, fetches the draft with authentication and renders it without caching. Budget real time for this — it's the feature editors miss most and the one most often descoped.

Do I still need an SEO plugin on headless WordPress?

You need the data it stores — titles, descriptions, canonicals, Open Graph values — but the plugin can no longer output anything, because it isn't rendering the page. Keep it as an editing interface, expose its fields through the API, and render the tags in the frontend yourself.

How do forms work in a headless WordPress site?

Not the way they did. WordPress form plugins output HTML and JavaScript into a theme that no longer exists. Build the form in the frontend and post it to an endpoint — either a custom WordPress REST endpoint or a separate form service. Plan for spam protection and email delivery too.

Will a headless Next.js frontend be faster than a WordPress theme?

It can be, especially statically generated and served from an edge network. But a well-built theme with proper caching and a CDN is also fast, and a careless Next.js frontend shipping too much JavaScript can be slower. Architecture sets the ceiling; the build decides where you land.

Topics

  • Next.js WordPress
  • headless WordPress Next.js
  • WordPress React frontend
  • Next.js CMS