Keep WordPress as a headless CMS, retire it, or move one section at a time? How each path affects editors, security and SEO risk, with a weighted scoring rubric to fill in for your own site.

Once Next.js is going to render your public site, the next question is what happens to WordPress. You can keep it as a headless CMS, retire it completely, or run both and move one section at a time.
The short answer: keep WordPress headless if your editors or a plugin-driven feature cannot move; migrate fully if developers own the content; phase it if the site is too big to freeze.
Each path changes something different: your editors’ day, your security workload, or your launch-day SEO risk. This guide compares them and ends with a rubric you can score for your own site. It is part of our WordPress to Next.js migration guide.
| Headless WordPress | Full migration | Phased migration | |
|---|---|---|---|
| What renders the site | Next.js | Next.js | Next.js for migrated sections, WordPress for the rest |
| Where content lives | WordPress | MDX in Git or a headless CMS | Both, until the last section moves |
| Editor impact | Minimal; same admin | High; new tool and workflow | Gradual |
| Systems to run and patch | Two | One | Two, for a while |
| SEO risk | Duplicate content and canonical mistakes | One big cutover on launch day; URLs change only if you choose | Smaller changes per section; keeping two stacks consistent |
| Best fit | Large editorial teams, complex content models | Developer-led teams, article and landing-page sites | Large or high-risk sites that cannot freeze content |
Choose headless when the people who publish are the bottleneck you cannot afford to disrupt: a newsroom with daily deadlines, a content team trained on the block editor, or a content model built from dozens of custom post types and ACF field groups that would take months to remodel.
| WordPress REST API | WPGraphQL | |
|---|---|---|
| Availability | Built into core | Plugin |
| Query shape | Fixed endpoints; trim with _fields, expand with _embed | Request exactly the fields and relations you need |
| Custom fields | ACF via “Show in REST API” | ACF via an extension |
| Caching | Standard HTTP caching | Usually needs a GraphQL-aware cache |
| Extra attack surface | None beyond core | One more plugin to patch |
Both are viable. WPGraphQL’s footing has improved: in 2024 its creator announced it was becoming a canonical WordPress plugin, with Automattic supporting its development. But every plugin in a headless stack is still code exposed to the internet: in 2026 WPGraphQL patched several vulnerabilities, including CVE-2026-40762, an unauthenticated SQL injection fixed in version 2.11.1. The REST API adds nothing beyond core, and its main drawback, over-fetching, is largely solved by _fields, which has supported nested properties since WordPress 5.3.

Editors expect “Update” to change the live site. Statically rendered pages can be refreshed on demand by calling revalidatePath from a Route Handler (the Next.js tab), and a small must-use plugin can call that handler whenever a post is saved (the PHP tab):
Three details in that hook are easy to get wrong:
__trashed before the status hook runs, so the hook strips it, or the deleted post stays live.post_updated hook refreshes the old path as well.Pages outside /blog that list posts, such as the home page or a feed, need their own revalidatePath call. A shared secret compared in constant time is the minimum. Signing the request body and verifying the signature is stronger, and it is what our own site does: its publish webhook checks the CMS’s signature before purging any cache.
Tagging fetches instead of paths? In Next.js 16 revalidateTag takes a second argument: the docs recommend revalidateTag(tag, 'max'), mark the single-argument form deprecated, and suggest { expire: 0 } for a webhook that needs the data gone immediately.
Losing “Preview” is the first complaint editors raise about headless setups. Next.js Draft Mode solves it: a secret-protected route turns Draft Mode on and redirects to the page, which then fetches unpublished content. Headless CMS vendors build on the same mechanism; Sanity’s Visual Editing setup for the App Router enables Draft Mode through a route its Studio calls.
The route only switches Draft Mode on. The rest of preview lives on the WordPress side and in one more page:
/blog/preview/[id] page should fetch the post’s latest autosave (or the post itself with context=edit) using an Application Password, and only when draftMode().isEnabled is true.noindex.X-Robots-Tag: noindex on every front-end response.yoast_head_json, canonical included. If WordPress’s site address is the CMS hostname, those canonical and Open Graph URLs will be too. Configure WordPress to use your real domain, or rewrite the hostname when you map the fields.Headless keeps WordPress, so it keeps WordPress’s patching load. Patchstack logged 11,334 new vulnerabilities in the WordPress ecosystem in 2025, 91% of them in plugins and 46% unpatched when disclosed. Hiding the CMS from the public internet narrows the exposure but not the update work. Add the Next.js side, which since July 2026 has pre-announced security releases roughly once a month, and plan for two update cycles.
Choose a full migration when developers already own the site, the content is mostly articles and landing pages, and retiring WordPress removes a real burden (security updates, hosting, plugin licences) rather than just a technology you dislike.
The cost lands on editors. They move to one of three models:
The best CMS for Next.js compares these in detail. Whichever you choose, the content has to be exported and converted once; how to export WordPress to MDX covers that pipeline.
A phased migration runs both stacks on one domain. Next.js serves what has been rebuilt and forwards every other request to WordPress, so you can move the blog first, then landing pages, then the rest, with a smaller URL change at each step.
Next.js documents this as incremental adoption. Its fallback rewrites are applied after dynamic routes and all static assets have been checked, just before the 404 page, so you can proxy everything Next.js does not handle to the old site without touching the config each time a section moves:
Four things to know before you rely on it:
app/[slug]/page.tsx, or a section route that calls notFound() for posts it has not migrated yet, answers with a 404 and never reaches WordPress. Avoid root-level dynamic segments during the migration, and move a section only when every URL in it exists in Next.js./:path* form, WordPress answered /old-page/ with a redirect to its own hostname and the visitor left the site. For any redirect WordPress still issues, map X-Forwarded-Host in wp-config.php, trusting it only from your proxy, so the Location header names the public domain./wp-admin/, /wp-login.php, /xmlrpc.php and /wp-json/ onto your public domain. Return a 404 for those paths in Proxy.What makes phased migrations go wrong is inconsistency between the two stacks:
X-Robots-Tag: noindex would deindex every proxied page on the public domain too. Make it conditional: have Proxy add a secret request header to proxied requests, and have WordPress send noindex only when that header is missing. Check both hostnames with curl -I.Define the exit criteria up front: when the last section moves, remove the fallback rewrite and retire the legacy origin. Phased migrations that never finish leave you paying for both stacks indefinitely.
Score each criterion from 1 to 5, where 1 means it strongly favours a full migration and 5 means it strongly favours headless. Multiply each score by its weight and add them up. The total runs from 14 to 70: above 46 points to headless, below 38 to a full migration, and anything in between is close enough to decide on cost, or to phase.

| Criterion | Weight | Score 5 (headless) when… | Score 1 (full migration) when… |
|---|---|---|---|
| Editor dependence on WordPress | 3 | Many editors, daily publishing, heavy training investment | Few editors, or developers publish |
| Content model complexity | 2 | Many custom post types, ACF groups, relationships | Posts, pages, a few taxonomies |
| Plugin-driven functionality | 3 | Memberships, LMS or ecommerce that must keep running | Only SEO, forms and caching plugins |
| Developer capacity | 2 | Small team that cannot rebuild the editing experience | Team can own a CMS or Git workflow |
| Security and ops appetite | 2 | WordPress operations already in place | Strong wish to run one system |
| Risk tolerance for launch day | 2 | Low; prefer to keep content in place | Comfortable with a single cutover |
If plugin-driven functionality scores 4 or 5, look hard at a phased approach: move the content-heavy sections to Next.js and leave the functional parts (a WooCommerce store, an LMS) on WordPress until their replacements are properly scoped.
Scores close, or not sure how to rate a row? In a free 15-minute audit we look at your site with you on a live screen-share and tell you which path we would take and why.
This site runs the full-migration end state: Next.js on Vercel, content in Sanity, three domains served from one deployment, and a publish webhook that refreshes cached pages when an editor publishes. For clients we usually recommend the same when their team is ready to leave WordPress, as ProEd did, and a headless or phased route when a plugin-driven feature has to keep running.
Fill in the rubric above with whoever owns your content. Ten minutes together will settle more than a week of debate about stacks.
Lunova Labs builds headless and fully migrated Next.js sites, and will tell you honestly which one your site needs.
Ready when you are