Migrating a production website to Next.js without losing a single URL comes down to three things: matching legacy routes one to one, configuring server-level 301 redirects for anything that genuinely moves, and validating metadata before you touch DNS. Most traffic drops during a rebuild are not caused by the framework. They happen because URLs change, canonical tags break, or the initial HTML arrives empty.
As an electrical engineer turned full-stack developer, I build web applications and run technical search strategy for automotive lead-generation platforms in US markets. When I migrated my own site to Next.js, the requirement was zero loss of search equity. A framework upgrade should improve speed and developer workflow without creating indexing churn.
Identical routing removes the risk entirely
The safest migration changes no URLs at all. Every time you move a path and lean on a 301, search engines have to discover the redirect, update their index, and transfer signals to the new destination. Redirects do pass authority, but keeping the path identical removes the delay completely.
Next.js uses file-based routing in both the App Router and the Pages Router, so you can replicate a legacy structure character for character:
- Match directory nesting with matching folder structures
- Preserve trailing slashes through the
trailingSlashsetting rather than by hand - Account for case sensitivity, which otherwise creates duplicate content
- Keep file extensions where the old platform served them
If the old site served /services/technical-seo/, the new application should serve that exact path natively. Crawlers then process the migrated page without detecting a structural shift at all.
Build the crawl map before you write code
Never map a site from memory or from the navigation menu. A production site contains blog posts, landing pages, archives, paginated indexes and media assets that never appear in primary navigation.
Pull the inventory from three independent sources:
- Crawl the live site with a technical auditing tool for every internal page, image and redirect
- Download the active XML sitemaps to capture what is actually submitted for indexing
- Export server logs or analytics to catch legacy URLs still receiving traffic or holding backlinks
Merge them into one canonical URL map and treat it as the acceptance checklist for the whole rebuild. Every URL on it must either exist natively in the new application or resolve through a server-level 301. If you want help planning a complex migration, see my technical SEO services.
Server-side redirects protect what genuinely moves
Some path changes are unavoidable — old file extensions, consolidated sections, renamed directories. Those redirects have to run on the server, before any HTML is rendered.
For static mappings, define them in the framework config so they execute at server level:
export default {
async redirects() {
return [
{ source: '/old-blog/:slug', destination: '/blog/:slug', permanent: true },
]
},
}For pattern-based rules involving regex or query parameters, use Middleware, which runs before the request completes and returns the 301 immediately.
Never use client-side JavaScript redirects or meta refresh tags for this. Crawlers treat them as unreliable, and destination pages can end up classified as soft 404s.
Server rendering preserves the initial payload
A major cause of indexation failure is switching from server-rendered HTML to client-side rendering. If pages fetch their content inside React state hooks, the initial HTML that Googlebot receives is a set of empty containers.
Modern crawlers do execute JavaScript, but relying on it introduces delay and risk for no benefit. The architecture should deliver complete markup in the first server response. In the App Router that means leaning on Server Components by default, and using static generation for content pages and posts so the HTML exists at build time.
If you are weighing architecture options, see my SEO website development services.
Canonical tags and headers need their own audit
Matching paths is only half the job. The new application has to emit identical titles, descriptions, canonical tags and structured data.
The common failure is a staging URL leaking into production metadata, or a canonical that disagrees with the requested URL. Either can drop a page from results.
- Set
metadataBasein the root layout so every canonical resolves against one origin - Define title and description templates so dynamic subpages cannot ship without them
- Confirm
robotspermits indexing in production while staging staysnoindex - Make Open Graph image URLs absolute and publicly reachable
Audit the head elements on a staging build before DNS cutover, not after.
Mistakes that actually cost traffic
- Changing domain and URL structure at the same time without a business reason
- Trailing slash inconsistency, where
/aboutand/about/both resolve - Forgetting image and media URLs that carry external links
- Client-side redirects instead of server-level 301s
- Rewriting H1s and internal linking patterns during the same release
- Leaving a staging
robots.txtin place after go-live
What to do next
- Crawl the existing site and build the baseline URL inventory
- Match Next.js routes to legacy paths character for character wherever possible
- Write server-side 301 rules for anything that genuinely changes
- Verify staging returns complete HTML and absolute canonicals on first response
- Check status codes across the full inventory before DNS cutover
- Watch Search Console indexation and server logs in the days after launch
If you want experienced engineering support to run the migration safely, get in touch.
Fazlay 