Migrating from WordPress to Next.js means moving a site from a PHP engine to a React framework with server-side rendering or static generation, transferring content, URL structure, and SEO signals into the new architecture without losing rankings. A properly executed migration keeps 100% of traffic by day 30 and typically delivers a 10-30% gain by day 90 thanks to a faster site. The key risk isn’t the stack switch itself - it’s losing what WordPress handled invisibly: automatic sitemap generation, canonical tags, redirects, category structure.
In Exceltic.dev’s web development projects, we regularly see the same pattern: a company decides to move from WordPress to Next.js for speed and security, but underestimates the amount of manual work needed on SEO infrastructure. WordPress, through Yoast or Rank Math, handles dozens of technical tasks automatically - without those plugins, Next.js requires writing the equivalent by hand. According to a migration breakdown from dashweb.agency, sites with a well-built redirect map don’t lose traffic by day 30 and see a 10-20% increase by day 90, and 30-50% by day 180. With a poorly built redirect map, the effect reverses: a drop that can last for months.
What follows is a step-by-step plan: what gets lost in a naive move, how a pre-migration audit works, what architecture to build on Next.js, and which Core Web Vitals metrics actually change after the move.
Why Companies Move from WordPress to Next.js
WordPress runs on PHP: every page request means a database query and on-the-fly rendering, unless server-level caching is configured. As traffic or the number of plugins grows, server response time increases, and LCP grows along with it.
Next.js is a React framework that supports static site generation (SSG), server-side rendering (SSR), and incremental static regeneration (ISR), serving ready-made HTML without a database call on every request.
Three specific reasons for migrating come up more often than others in projects. The first is performance: on shared hosting with 15-20 active plugins, Time to First Byte often exceeds 800 ms, while a statically generated Next.js page served from a CDN loads in 50-200 ms. We covered the mechanics of this slowdown in more detail in the article on why WordPress slows down a site.
The second reason is security. Every installed plugin is a separate entry point for exploits, and the number of new vulnerabilities in the WordPress ecosystem grows year over year: a detailed breakdown is in the article on WordPress plugin vulnerabilities. A static Next.js site simply has no database or admin panel to break into.
The third reason is total cost of ownership. Managed WordPress hosting with acceptable performance (WP Engine, Kinsta) costs 30-300 dollars a month depending on traffic, plus paid plugin licenses. Next.js on Vercel fits within the free tier for most marketing site scenarios, or costs a few tens of dollars a month under heavy load.
What Gets Lost in a Naive Migration
A naive migration is moving content without a URL mapping and without auditing the technical SEO signals that WordPress generated automatically. Below are the specific points of loss that stay invisible until traffic starts dropping 2-4 weeks after launch.
URL structure. By default, WordPress builds URLs following the pattern /category/post-slug/ or /post-slug/, depending on permalink settings. Next.js has no built-in URL logic - if the new routing structure doesn’t match the old one for even a subset of pages, those pages lose their accumulated SEO equity without a 301 redirect.
Redirects. WordPress plugins (Yoast, Redirection) store the redirect map in the database and apply it at the PHP level. This map doesn’t transfer automatically during a migration - it needs to be exported, checked for accuracy, and carried over into next.config.js or middleware as an explicit list.
Plugins and functionality. Forms (Contact Form 7, Gravity Forms), calculators, galleries, embedded booking widgets - all plugin functionality runs on PHP hooks that don’t exist in Next.js. Each such plugin has to be either replaced with a SaaS widget or rebuilt from scratch as a React component.
Images and media. WordPress stores its media library in /wp-content/uploads/ and automatically generates several sizes for each image. When moving to Next.js, images either migrate to public/ or move to a CDN (Cloudinary, Vercel Blob) - in both cases, the old paths need to be preserved or redirected to the new ones, or external links to images from Google Images and social platforms will start returning 404s.
Technical SEO signals. Sitemap.xml, robots.txt, canonical tags, Open Graph markup, schema.org microdata - in WordPress, a plugin generates all of this on every publish. In Next.js, all of these elements need to be assembled manually through generateMetadata and file conventions (sitemap.ts, robots.ts).
Pre-Migration Audit: What to Inventory
A pre-migration audit is a full inventory of the old site’s URLs, content, and technical signals, completed before development on the new stack begins. Skip this step and the redirect map gets built from memory - and it’s almost always incomplete.
The inventory sequence that removes most of the risks described in the previous section:
- Export all URLs. Crawl the site with Screaming Frog or Sitebulb to get a full list of indexable pages, including pagination, tag pages, and date archives.
- Export Google Search Console data. Pull at least 12 months of data: the top 500 queries by impressions, the highest-traffic pages, and currently indexed URLs. This is the priority list of pages that cannot be lost.
- Content type map. Record every custom post type, taxonomy, and ACF field - each one will need its own data model in Next.js.
- List of plugins with their functionality. Not just a list of names, but exactly what each plugin does on the front end - forms, pop-ups, chat widgets, price calculators.
- Media file inventory. How many images, in what format, what total size - this determines whether to move the media library as-is or convert it to WebP/AVIF during the migration.
We put together a more detailed hour-by-hour checklist in the article website audit before migration.
Architecture of the New Next.js Stack
The architecture of a WordPress-to-Next.js migration is built around three decisions: where content lives, how the page renders, and where the site is hosted. Here’s the reasoning behind each.
Content: headless CMS or MDX. A headless CMS is a content management system with no front end of its own, delivering data through an API instead of rendering HTML itself. For a site with frequent publishing (a blog, a knowledge base), it makes sense to move content into Sanity, Contentful, or Strapi - editors get a familiar interface, developers get control over rendering. For a site with infrequent content changes (5-10 pages, landing pages), MDX files directly in the repository are often enough - simpler to maintain and no separate CMS subscription required. A breakdown of specific headless CMS options is in the article Sanity vs Contentful vs Strapi.
Rendering: SSG or ISR. For content pages that don’t change minute to minute, static generation (SSG) gives the best Core Web Vitals results - the HTML is built ahead of time, and the server runs no logic per request. For pages with frequently updated data (prices, stock availability), incremental static regeneration fits better - the page updates in the background on a schedule without blocking the user.
Hosting: Vercel or self-hosted. Vercel is the company that develops Next.js, so deployment and edge caching work with no extra configuration. A self-hosted setup (a Node.js server behind Nginx, Docker) makes sense if the company already has a data-residency requirement for a specific region or existing infrastructure to reuse.
Why Next.js was the right choice over Astro for this scenario - including a comparison of Core Web Vitals and the team’s learning curve - is covered separately in the article Next.js vs Astro for a marketing site.
Step-by-Step Migration Process
Below is the sequence that, in practice, brings the risk of traffic loss close to zero when the steps are followed in order.
Step 1. Set Up the Project and Content Model
Create the Next.js project (App Router), define content types (posts, pages, categories) to match the structure recorded during the audit. If content is moving into a headless CMS, this is the step to set up the field schema and import from the WordPress export (the WXR file is converted to JSON via wordpress-export-to-markdown or a similar script).
Step 2. Migrate Content and Media
Import posts and pages, preserving the original publication dates (important for content-freshness signals). Images either move into public/ with their original paths, or get uploaded to a CDN with aliases preserved for the old URLs.
Step 3. Build the SEO Infrastructure
Set up generateMetadata for each page type, generate sitemap.xml and robots.txt through Next.js file conventions, and add JSON-LD markup (Article, BreadcrumbList, FAQPage where a page has questions). Example generateMetadata configuration for a post page:
Example generateMetadata for a post page
export async function generateMetadata({ params }: { params: { slug: string } }) {
const post = await getPostBySlug(params.slug);
return {
title: post.seoTitle,
description: post.seoDescription,
alternates: { canonical: `https://example.com/blog/${post.slug}/` },
openGraph: {
title: post.seoTitle,
description: post.seoDescription,
images: [post.ogImage],
type: 'article',
},
};
}
Step 4. Build the Redirect Map
Map every URL from the audit to its new address. If the structure hasn’t changed, no redirect is needed - but confirm that explicitly rather than assuming it. The redirect list is wired up through redirects() in next.config.js or through middleware for dynamic rules:
Example static redirects in next.config.js
module.exports = {
async redirects() {
return [
{
source: '/category/wordpress-tips/:slug',
destination: '/blog/:slug',
permanent: true,
},
{
source: '/wp-content/uploads/:path*',
destination: '/media/:path*',
permanent: true,
},
];
},
};
Step 5. Test on a Staging Domain
Crawl the staging version with Screaming Frog, cross-check it against the original URL list, and confirm that none of the top 500 pages by Search Console impressions return a 404 or 500. Check canonical tags, hreflang (if the site is multilingual), and that Open Graph previews render correctly.
Step 6. Launch and Monitor the First Weeks
Switch DNS, submit the new sitemap.xml to Google Search Console, and manually request reindexing for the 10-20 highest-traffic pages. For the first 2-4 weeks, check the Coverage report in Search Console daily for new 404 errors or unexpected exclusions from the index.
A more complete breakdown of how SEO signals behave at launch is in the article SEO during site migration. The general principles for preserving SEO equity when changing domains or URL structure are also covered in Google’s guide to site moves.
Core Web Vitals Before and After Migration
Core Web Vitals is a set of Google metrics measuring a page’s real-world speed and stability for the user: LCP (largest content load), CLS (visual stability), and INP (interaction responsiveness). The “good” thresholds according to web.dev: LCP under 2.5 seconds, CLS under 0.1, INP under 200 ms.
In a typical migration project - a 200-500 page content site moving from WordPress on shared hosting to Next.js deployed on Vercel - the metrics shift within the following ranges:
- LCP: from 3.5-5.5 seconds down to 1.2-2.2 seconds - thanks to eliminating the per-render database query and serving static HTML through a CDN.
- CLS: from 0.15-0.3 down to 0.02-0.08 - thanks to explicit image dimensions via
next/imageinstead of dynamically loaded widgets and ad blocks. - INP: from 300-500 ms down to 100-180 ms - thanks to less third-party JavaScript (trackers, plugin widgets), which tends to accumulate unchecked on WordPress.
Mobile PageSpeed Insights scores for these projects typically rise from the 35-55 range to 85-98. The exact numbers depend on how much media is on the page and how much third-party JavaScript (chat widgets, analytics, pixels) gets carried over with the site - every extra script eats into the gains from switching stacks.
Common Mistakes During the Move
Some mistakes repeat across migration projects regardless of site size. Here are the most common ones.
Forgetting about pagination and date archives. Screaming Frog only finds pages that are linked to - category pagination URLs and monthly archive URLs often aren’t manually tracked and fall out of the redirect map if you rely on the crawler alone without cross-checking server logs or Search Console.
Moving images without preserving paths. If old image URLs from /wp-content/uploads/2024/03/ don’t redirect to the new location, traffic from Google Images is lost and external links to the images from other sites break.
Not checking canonical tags on staging. A common mistake is leaving the staging domain indexed, or having the default canonical point somewhere other than the final domain, which causes Google to briefly confuse the production and test versions after launch.
Turning off redirects after a few months. 301 redirects need to stay active for at least 6-12 months after launch - Google processes old URLs gradually, and some external links from other sites will physically never get updated.
Moving content without checking internal linking. WordPress plugins (Yoast, Rank Math) often build automatic “related articles” blocks. After moving to Next.js, these blocks need to be either recreated with logic based on tags and categories, or key internal links need to be placed manually - without them, the transfer of SEO equity between pages drops off.
Who This Migration Makes Sense For
A WordPress-to-Next.js migration makes sense for companies with a marketing or content site and 15-20+ employees, where WordPress has already hit a wall on performance or maintenance cost, and the team is ready to take on development through code instead of a visual editor.
It’s a worse fit for a scenario where non-technical staff edit content directly in a visual editor every day without developer involvement - for those teams, a headless CMS with a friendly UI on top of Next.js covers the need, while plain MDX in the repository creates a new bottleneck.
Frequently Asked Questions
How long does a WordPress-to-Next.js migration take?
For a site with 50-100 pages and a typical content mix (blog, landing pages, a few forms), migration usually takes 4-8 weeks, including audit, development, testing, and monitoring indexing after launch. Sites with non-standard plugin functionality (calculators, user accounts, complex catalog filters) need more time to rebuild that logic in React than to move the content itself.
What happens to Google rankings right after the move?
With a correct redirect map and preserved technical signals, the short-term dip is usually minimal or nonexistent - Google reprocesses 301 redirects within a few days to a few weeks. A more noticeable drop happens when some URLs are left without a redirect or the canonical is set up incorrectly - in that case, some pages temporarily fall out of the index until it’s fixed manually.
Do you have to fully abandon WordPress, or can it stay as a content source?
Both approaches work. Some companies keep WordPress running in headless mode and pull content through the REST API or WPGraphQL, preserving the familiar editing interface for the marketing team. Others move content entirely into a separate headless CMS or MDX to remove the dependency on PHP infrastructure and the security risks that come with it.
Which hosting should you choose for Next.js after moving from WordPress?
Vercel is the fastest path for teams without a dedicated DevOps resource: Git-based deployment, edge caching, and pull request previews all work out of the box. A self-hosted setup on your own server or in a Docker container makes sense if the company has data-residency requirements for a specific region, or already has infrastructure that’s cheaper to reuse.
Can you migrate the site in parts instead of all at once?
Yes, and for larger sites this lowers the risk. A common approach is to move the blog or a specific section to Next.js first, through a reverse proxy (for example, an Nginx rule or Vercel rewrites that routes /blog/* to the new Next.js service while leaving the rest of the traffic on WordPress), then gradually migrate the remaining sections. This requires careful routing setup at the DNS or proxy level, but it lets you roll back a single section without risking the entire site.
What to Do Next
- Audit your current site: a full URL list, 12 months of Search Console data, and an inventory of plugins and media.
- Decide on a content model - a headless CMS for frequent publishing, MDX for a static set of pages.
- Build the redirect map before development starts, not after launch.
- Keep the old and new sites available in parallel on staging at least until you’ve fully verified the technical signals.
If you’re currently evaluating a move from WordPress to Next.js and want to avoid the typical traffic losses, describe your site’s size and key plugin functionality to the Exceltic.dev team. We’ll map out the migration risks and give you an honest timeline estimate.