Skip to content
WordPressNext.js
Migration Guide

WordPress to Next.js Migration Guide

Moving off WordPress is really two different projects: replacing the theme (frontend) and deciding what happens to the content editing workflow. Conflating them is how these migrations blow up.

What Changes
  1. PHP theme templates become React components with static generation
  2. The WordPress editor is either kept (headless) or replaced (full migration)
  3. Plugins are replaced one function at a time — forms, SEO, analytics, search
  4. Hosting moves from a PHP server to static/edge hosting (Vercel, Netlify)
  5. URL structure must be preserved or 301-mapped, or rankings pay for it
Migration Path

Decide the content question first: headless WordPress (keep wp-admin, fetch via WPGraphQL/REST) if non-developers edit weekly, or full export to Markdown/a code-based data layer if content changes rarely. Everything else — components, hosting, redirects — follows from that one decision.

In detail

Headless or full export: the fork in the road

Headless keeps WordPress running as a content backend — editors use wp-admin exactly as before, and Next.js fetches posts at build time through WPGraphQL or the REST API. Choose this when non-technical people publish weekly and retraining them is a real cost. The price: you still run, patch, and secure a WordPress install; you've added a system, not removed one. Full export converts posts to Markdown or MDX (or a structured data file) that lives in the repo, and WordPress is switched off entirely. Choose this when content changes monthly or less, or when developers are the ones editing anyway.

The honest heuristic is publishing frequency crossed with who publishes. A marketing team shipping three posts a week: headless, or they will hate you. A company site where the blog gets a post a quarter: full export, and delete the attack surface — no more plugin CVEs, no more PHP updates, no database to back up. There's a middle path worth naming: full export plus a git-based CMS layer for the occasional edit. This site takes the code-based approach — every blog post and pSEO page lives in typed TypeScript data files, which is what makes generating a few hundred static pages trivial.

The SEO migration is the actual project

A WordPress site that ranks has years of accumulated equity in specific URLs, and the migration's success is measured by how little of it you spill. Rule one: keep the URL structure identical where possible — if posts live at /blog/post-name, generate the Next.js routes at exactly those paths. Where structure must change (dropping date-based permalinks, say), build a complete 301 map — every old URL to its new home — and ship it in next.config redirects or middleware before launch, not after Search Console starts showing 404s. Crawl the live site first for the canonical URL inventory; the sitemap alone misses old URLs that still hold backlinks.

Then re-implement what SEO plugins were silently doing: titles and meta descriptions move to generateMetadata, per-post canonical tags, OpenGraph images, an XML sitemap from app/sitemap.ts, and structured data as JSON-LD components. Check the odd corners — category and tag archive pages, pagination, RSS feeds if anything subscribes to them. Done right, rankings typically dip slightly for a few weeks and recover above baseline, because the Core Web Vitals improvement from static HTML over a plugin-heavy PHP stack is usually dramatic and Google measures it.

Replacing the plugin stack

Every active plugin needs an explicit answer, and the audit usually shocks people — sites run 30 plugins where five do something visible. Contact forms become a route handler posting to an email API like Resend, which is a genuinely nicer setup than any form plugin: you own the markup, the validation, and the deliverability. Analytics plugins become a script tag or a lightweight analytics package. Search over a static site works well with a build-time index (Pagefind, or Fuse.js for smaller sites) — no server needed. Caching and performance plugins simply cease to exist as a category; static generation is the thing they were all approximating.

The hard cases are plugins that are actually applications: WooCommerce, membership systems, LMS plugins, booking systems. Do not try to rebuild these as a side quest inside a site migration — either the migration scopes them out (keep that subdomain on WordPress), or they move to a dedicated service (Stripe payment links or a proper e-commerce backend), or the project is honestly re-scoped as an application build, which is a different budget. Naming this in the first conversation is the difference between a two-week migration and a six-month one.

Content export mechanics

For the full-export path, the WordPress XML export (Tools → Export) is the starting point, and converters like wordpress-export-to-markdown handle the bulk transform to Markdown with frontmatter. Expect to clean up after it: shortcodes from old plugins left inline ([gallery], [caption]), HTML entities, inline styles pasted from Word a decade ago, and image references pointing at wp-content/uploads with WordPress's generated size suffixes. A cleanup script gets you 95% of the way; budget a manual pass for the posts that matter most.

Images deserve their own step. Download the uploads directory, deduplicate the resized variants (keep originals only — Next.js generates sizes itself), convert to modern formats, and rewrite the references during the Markdown transform. For the headless path most of this disappears — content stays in WordPress — but you inherit a different task: mapping Gutenberg block markup or ACF fields onto React components, which is straightforward for standard blocks and a real project if the site leaned hard on a page builder like Elementor. Page-builder sites are the one case where "migration" is honestly "redesign", because the content and its presentation were never separate to begin with.

Other migration guidesView all →
Related

Planning this migration?