WordPress to Next.js migration without losing a single ranking.
Headless WordPress with WPGraphQL, or full migration to Sanity, Payload, or Storyblok. Twelve thousand WordPress sites of practice. Redirect maps generated from Search Console plus Ahrefs. Yoast and Rank Math metadata transported byte-identical.
12,000+ WordPress sites shipped Headless or full re-platform Redirect map from GSC + Ahrefs Yoast/Rank Math metadata transport
WHY DO TEAMS MIGRATE OFF WORDPRESS
Honestly? Mostly because Lighthouse never quite gets there.
I have spent a lot of mornings explaining to founders why their lovingly-built Elementor site keeps benching at 62 in PageSpeed Insights even after three caching plugins, a CDN, and a fresh hosting move. There is a ceiling. You can prod a classic WordPress front-end into the low 80s if you really care, but every plugin update is a regression risk and every page builder release ships another half-megabyte you did not ask for.
The teams I see migrate fall into three rough buckets, and they almost never overlap.
The performance bucket
A Series-A SaaS marketing site, currently on WP Engine, paying for Elementor Pro plus three add-on packs. Lighthouse 64 on mobile. INP at 380 ms. They have a content team that ships two posts a week and an engineering team that wants to ship onboarding flows, not WordPress patches. The Next.js rebuild gets them to 96, and the engineers stop touching wp-admin.
The engineering bucket
Three TypeScript engineers. One of them is on call for the marketing site. They open wp-admin once a fortnight and curse. The whole "is this PHP 7.4 or 8.1, what version of WooCommerce did the agency leave us on" routine is a tax on people who would happily ship in Astro for half the agitation. Migrate, give them a Next.js or Astro repo with proper CI, and the on-call rotation gets smaller.
The security bucket
Less common, more decisive. A board-level mandate that public-facing surfaces should not be running PHP. Or a security incident that shipped a patched plugin three weeks late. Headless WordPress on a non-public origin satisfies the policy without forcing the editorial team to learn a new CMS. The wp.example.com goes private; the front-end is just a static site on Vercel. Most pen tests stop being interesting.
WHAT MIGRATION PATHS DO YOU OFFER
Three. Genuinely three, not the marketing-page kind that all collapse into the same scope. Each one suits a different team.
Path 1 — keep WordPress, replace the front-end
Headless. WP stays as the editor surface. Yoast keeps doing its thing in the admin. ACF keeps doing its thing in the admin. The public site gets rebuilt in Next.js or Astro and pulls content over WPGraphQL. Editors barely notice the migration day apart from the URL bar showing the new front-end domain. This is the most common path I scope; about two thirds of recent migrations have gone this way.
When it is right: editorial team is happy in WordPress, the engineering issue is purely front-end, and you do not want to migrate twelve thousand pages of Yoast metadata.
Path 2 — leave WordPress entirely
Migrate everything to Sanity, Payload, Storyblok, or Contentful. Shut down WordPress on launch. Newer codebase, cleaner content model, no PHP anywhere. The migration cost is higher because you are moving content, not just rebuilding the front-end. Worth it when the editorial team specifically wants out of WordPress, or when the content model needs more rigour than ACF flexible content can give you.
When it is right: you actually want a different CMS, not just a different front-end.
Path 3 — hybrid
Some content stays in WordPress, some moves elsewhere. Real example pattern: blog stays in WP because the editorial team is mature and Yoast is doing real work; product pages move to Payload because the schema needs proper relations and validation. Front-end is one Next.js app reading from both backends. More architecture but sometimes it is the right answer.
When it is right: two genuinely different content shapes on the same site, and forcing them into one CMS is making someone's life worse.
HOW DOES THE REDIRECT MAP GET BUILT
This is where migrations live or die, and it is also the bit teams routinely skimp on. Without a complete map you lose rankings on day one. With a partial map you lose them slowly over six weeks while you tell yourself the dip is just seasonality.
The map gets built from three independent sources before any code ships.
- Search Console export — every URL Google has crawled and considered indexable in the last 16 months. This is the canonical list of what Google currently expects to find at your domain.
- Ahrefs or Semrush export — every URL with at least one referring domain pointing at it, sorted by referring-domain count. These are the URLs where 301 preservation matters most. If you 404 a page with 200 backlinks, you have just thrown away 200 backlinks.
- WordPress sitemap — your current XML sitemap export. Catches pages that may not have backlinks or organic traffic but are still in the structure. Useful as a third pass to find anything the first two missed.
Three lists, deduped, mapped to new URLs, shipped as 301s in vercel.json or netlify.toml at the edge. Not 302s. Not JavaScript-driven redirects. Not a meta refresh. URLs that are genuinely retired get 410. URLs that have changed slug get 301. The build linter fails the deploy if any pre-migration URL is missing from the map.
I have watched a 5,000-page migration lose 60% of its organic in eight weeks because the redirect map was 87% complete and "the rest are not worth worrying about." The 13% were worth worrying about. They always are.
WHAT HAPPENS TO PLUGINS DURING MIGRATION
Plugin audit on day one. Every active plugin lands in one of four buckets, and the bucket decides the work.
Stays as is
Plugins that run server-side and never touch the public front-end. WP Migrate DB, BackWPup, server-side analytics, role-management. They keep working because nothing about their job involves rendering HTML to a visitor. About 20-25% of the plugin count usually falls here.
Replaced by code
Plugins that inject HTML or JavaScript into the front-end. Most SEO plugins (the metadata transports, the front-end output is custom). Most form plugins (replaced by Next.js endpoints or by ConvertKit / HubSpot / Mailchimp). Most schema plugins (replaced by hand-written templates that emit cleaner JSON-LD anyway). Cookie banners get rewritten in TypeScript. About 30-40% of the plugin count.
Replaced by service
Plugins that wrap a third-party. The HubSpot embed plugin becomes a HubSpot Forms API call. The Stripe payment plugin becomes Stripe Elements. Zapier and Make stay where they are because they live outside WordPress anyway. About 10-15% of the count.
Cut entirely
Plugins that exist purely because the WordPress front-end needed them. Caching plugins (Vercel handles this). Most security plugins (the public attack surface is gone). Performance optimisation plugins (build-time concern now). And the always-amusing "I have no idea why this is here, it has been deactivated for two years but we never deleted it" group. Plugin counts on the WordPress side typically drop 70-80% post-migration. That is part of the win.
HOW DO YOU PRESERVE EDITORIAL WORKFLOW
Preview and drafts
Editors hit Preview in wp-admin. WordPress mints a JWT preview token. The Next.js front-end reads the token, fetches the draft via WPGraphQL bypassing the static cache, and renders. Draft URLs are signed, never indexable, never cached publicly. The one-click preview UX stays exactly as it was. Most editors never notice the migration day on the editorial side.
Comments, revisions, roles
Untouched on the back-end. Comments on posts can stay WordPress-native and render headless via WPGraphQL, or get replaced with Disqus / Giscus / a custom system if your team wanted that anyway. Revisions are unchanged — every post still has its full history accessible from the WordPress editor. User roles, permissions, multi-author setups, all preserved.
Yoast and Rank Math
Both transport. Yoast SEO for WPGraphQL exposes every field — focus keyword, meta title, meta description, canonical, OG, Twitter card, schema breadcrumb — as queryable GraphQL. Rank Math has the equivalent. The Next.js layout reads the typed response and renders meta tags identical to what Yoast or Rank Math would have output on classic WordPress. Editors keep editing in the same plugin UI; the migration is invisible from their side.
WHAT IS THE PROJECT TIMELINE
Week 1: discovery and scoping
Plugin audit. Content audit. Search Console + Ahrefs export for the redirect map source. Current performance baseline. Decision on path one versus two versus hybrid. Output: written SOW with a fixed price and a milestone payment schedule. By end of week one you know exactly what you are paying for.
Weeks 2-4: foundation
Repos in your GitHub, not ours. Hosting in your accounts. WPGraphQL (or new CMS) configured. Next.js or Astro scaffolding shipped. SEO linter and redirect-map ingestion plumbed. Design tokens migrated. By the end of week four the foundation is real and the team is shipping pages.
Weeks 5-10: build
Templates ported, page-by-page. Daily Looms from the lead engineer in your Slack. Weekly mid-build review call. Tickets in Linear or Jira or whatever you already use. Edge cases caught as they surface. This is the boring middle of the project where most of the actual code gets written.
Weeks 10-12: pre-launch QA
Manual cross-browser. Mobile audit. Accessibility audit at WCAG AA. Real-device Core Web Vitals (not lab Lighthouse). SEO linter green. Schema validator green. Redirect map verified URL-by-URL against Search Console export. The cutover plan written and rehearsed.
Week 12: launch
DNS cutover at a window you choose. Most go on a Tuesday or Wednesday morning, low-traffic. Front-end is already running on a staging domain; the cutover is a DNS flip. Engineering on standby for 24 hours. Search Console submitted with the new sitemap. Ahrefs and GA annotated.
Weeks 12-16: hyper-care
Daily Search Console monitoring for index anomalies, redirect chain warnings, schema errors. Weekly traffic comparison against baseline. Bug fixes prioritised over features. By week 16 the site is stable and we either hand off cleanly or move into an ongoing care plan.
FREQUENTLY ASKED QUESTIONS
Why migrate from WordPress to Next.js?
Three reasons. Performance — a Next.js front-end on Vercel typically clears 95+ Lighthouse on shared hosting where WordPress struggles to clear 70. Developer experience — TypeScript, component frameworks, edge deployment, version-controlled deploys. Security — the public attack surface drops to near zero when WordPress only runs as a back-end on a non-public origin. The trade-off is that any plugin-based functionality has to be replaced or replicated in code.
Should I go fully headless or fully off WordPress?
Two valid paths and one wrong one. Path one is headless WordPress — keep WordPress as the editorial back-end and rebuild the front-end in Next.js, fetching content via WPGraphQL. Editors keep wp-admin and you keep most of the editorial workflow. Path two is fully off WordPress — migrate content to a modern CMS like Sanity, Payload, Storyblok, or Contentful, and rebuild front-end and admin in Next.js. The wrong path is staying classic WordPress with a Next.js wrapper that calls WordPress on every request — you inherit WordPress's performance ceiling without the editorial benefit.
Will my SEO survive the migration?
Yes if the migration is done correctly. Three rules. Preserve every URL or 301 it to its new home — no exceptions, no soft 404s. Bridge Yoast or Rank Math metadata into the new front-end so titles, descriptions, and canonicals stay byte-identical post-migration. Keep schema on every page; if you cannot ship the same schema types, ship better ones. We bake all three into a build-time SEO linter that fails the build if any indexed URL would 404 post-cutover.
How long does a WordPress to Next.js migration take?
A 30-100 page marketing site migration runs 8-12 weeks. A 500-page content site with custom post types, ACF heavy use, and Yoast metadata runs 12-16 weeks. WooCommerce migrations are a separate project shape — typically 14-22 weeks because of cart, checkout, payment, and order history complexity. Bigger or more complex sites take longer; we will give you an honest range on the discovery call.
How do you handle the redirect map?
Three sources of URLs go into the map. Every URL currently indexed by Google (pulled from Search Console). Every URL with backlinks pointing at it (pulled from Ahrefs). Every URL in the WordPress sitemap. We dedupe, map each old URL to its new home, and ship the map as 301s in vercel.json or netlify.toml — never as 302s, never as JavaScript redirects. If a URL is genuinely retired we 410 it; if a URL has changed slug we 301 it. The build-time linter fails the deploy if any pre-migration URL is missing from the redirect map.
How do you migrate ACF and custom post types?
ACF fields are exposed via WPGraphQL for ACF and queried by the new Next.js front-end. Custom post types either stay in WordPress and stream over WPGraphQL (if the editorial workflow is good), or get modeled in the new CMS (Sanity, Payload, etc.) and bulk-imported. The decision usually comes down to who edits what — if marketing is happy in wp-admin, keep it; if engineering wants more control over content modelling, migrate.
What happens to Yoast or Rank Math metadata?
It transports. Yoast SEO for WPGraphQL exposes every Yoast field — focus keyword, meta title, meta description, canonical, OG image, schema breadcrumb — as queryable GraphQL. Rank Math has an equivalent. The new Next.js front-end reads from the GraphQL response and renders the meta tags, exactly as Yoast or Rank Math would have on the classic WordPress front-end. Editors keep editing in the same plugin UI. The migration day is invisible from the editor's perspective.
What about WooCommerce?
WooCommerce migrations are a separate practice. Two paths. Keep WooCommerce as the headless commerce back-end (via WooGraphQL or the REST API) with a Next.js storefront — works for catalogues under about 5,000 products. Or migrate fully to a modern commerce platform — Shopify Hydrogen, BigCommerce, Medusa, Saleor — when WooCommerce becomes the bottleneck. We have shipped both. The right answer depends on your catalogue size, fulfilment integrations, and whether your team wants to keep WordPress at all.
How do you handle plugin-based functionality?
Audit every active plugin on the WordPress site at the start of the project. Each one falls into one of four buckets. Stays as is — plugins that run server-side and do not inject into the front-end (security plugins on the back-end, backup plugins). Replaced by code — plugins that inject HTML or JavaScript get rewritten as Next.js components or replaced by a modern equivalent (mailchimp signup → ConvertKit form, Yoast → bridged via WPGraphQL). Replaced by a service — plugins that wrap a third-party service get replaced by a direct API call (HubSpot embed → HubSpot Forms API, Stripe plugin → Stripe Elements). Cut entirely — plugins that exist only because the WordPress front-end needed them no longer apply on Next.js. Most projects ship with a plugin count that drops by 70-80% after migration.
How do you handle preview, drafts, and editorial workflow?
Next.js Draft Mode plus a JWT preview token. WordPress mints a JWT when an editor clicks Preview; Next.js verifies the token, fetches the draft via WPGraphQL bypassing the static cache, and renders. Editors see live previews of unpublished posts at a draft URL that nobody else can access. Comments, revisions, and the rest of WordPress editorial UX stay exactly as they were. Most editors do not notice the migration day in the editorial UI.
What does it cost?
A 30-100 page marketing site migration: 25,000-50,000 USD. A 500-page content site: 50,000-90,000 USD. WooCommerce headless rebuild: 60,000-150,000 USD. The biggest variable is custom post type and ACF complexity — the more bespoke the WordPress install, the more migration work. We always give a fixed price after a one-week scoping phase, never an open-ended hourly engagement.
WHAT THE FIRST 48 HOURS LOOK LIKE
Book a 30-minute migration call. Bring your current WordPress URL, your active plugin list (a screenshot of the Plugins page is fine), and what is bothering you about staying on WordPress. By the end of the call you will know whether headless WordPress or a full re-platform is the right path for you, what the redirect map and metadata transport look like for your specific site, and a price range. If migration is the wrong move I will tell you to stay where you are.