Next.js11 min read

How to Migrate from Pages Router to App Router

A field-tested migration how-to for moving Next.js apps from Pages Router to App Router without breaking SEO or shipping velocity.

I am Sajan Acharya, a Senior Software Engineer based in Kathmandu. Migrating from the Pages Router to the App Router is one of the most common Next.js projects I see—and one of the easiest to over-scope. Teams either freeze forever on Pages or attempt a weekend rewrite that breaks auth, analytics, and rankings. This how-to is the middle path I use: inventory, dual-run, migrate high-value routes first, then retire Pages when the risk is boring. Calm migrations look slow from the outside and feel fast once production stays green.

Before you move a single file, confirm App Router is the right destination for your product constraints. If you are still evaluating fit, read how to choose Next.js for production apps. Migration is expensive enough that you should not do it as fashion. You do it to unlock server components, nested layouts, modern metadata, and a routing model aligned with current React. If those benefits do not map to near-term product goals, improve the Pages app first and revisit later.

Inventory routes, data fetching, and SEO contracts

Export a list of every Pages route: public, authenticated, API routes, and special files like _app, _document, and middleware. Note getServerSideProps, getStaticProps, and client-only pages. Capture current titles, canonicals, redirects, and sitemap entries. Those SEO contracts must survive the move. A migration that changes URL shapes without redirects is a ranking incident wearing a refactor badge. I keep a column for “must not change URL” and treat it as non-negotiable unless marketing explicitly approves a redirect plan.

Classify each route by business value and technical risk. High-traffic marketing pages and content hubs often migrate early because App Router metadata and layouts pay off quickly. Complex admin flows with tangled client state can wait. Shared UI should move into packages or a components folder both routers can import so you do not duplicate design systems during the dual-run period. Also list third-party scripts and consent banners; they break more often than people expect when _app disappears.

Run both routers, then migrate in slices

Next.js allows Pages and App directories to coexist. Use that. Create the app directory, establish a root layout, and move one low-risk public route first as a proof. Convert data fetching to server components or route handlers deliberately—do not paste getServerSideProps logic blindly into client components. Replace custom _document concerns with layout-level HTML structure and the metadata API. Celebrate the first green cutover, then widen the blast radius only as confidence grows.

Each slice should include tests or at least a manual checklist for auth gates, analytics events, and mobile layout. Dual-running increases cognitive load, so time-box it. Freeze cosmetic refactors unrelated to the migration. The goal is parity first, elegance second. Teams that polish while migrating invent two bugs for every one they remove. I also ask product to pause non-critical landing-page experiments during SEO-critical cutovers so analytics noise does not look like a migration regression. Communicate the soak window to stakeholders before the first public route moves; surprise freezes damage trust faster than a careful dual-run ever will.

  • Freeze new Pages-only features; new work prefers App Router when feasible
  • Preserve exact public URLs or ship redirects on day one of each cutover
  • Move shared providers carefully—auth and theme often break first
  • Retest Core Web Vitals and Search Console coverage after each batch
  • Migrate API routes to route handlers only when you gain clarity, not for sport
  • Delete Pages files only after monitoring shows parity for a defined soak period

Protect auth, analytics, and third-party scripts

Most migration bugs hide in providers. Session context, feature flags, and tag managers that lived in _app need a thoughtful App Router equivalent—often a combination of server session reads and a small client provider boundary. Avoid wrapping the entire tree in unnecessary client components; that undoes the point of the move. Middleware should keep protecting the same path prefixes after files relocate. Verify cookie domains and secure flags still match after layout changes.

SEO-sensitive pages deserve a checklist each time they cut over: status codes, canonical tags, H1 parity, structured data if present, and internal links that still resolve. For the broader SEO playbook that should guide those checks, see how to build SEO-friendly apps with Next.js. Migration without SEO verification is how quiet traffic drops become quarterly postmortems. Screenshot diffs of rendered HTML for top landing pages before and after; humans catch missing intros that automated tests miss.

Finish with cleanup and team conventions

When the last meaningful Pages route is gone, remove dead _app patterns, update docs, and teach the team where layouts, loading UI, and error boundaries live. Codify rules: server components by default, client only for interactivity, fetch caching intentional. From Kathmandu I often pair with remote teams during the dual-run window so reviews catch anti-patterns early. A short internal ADR describing “how we route now” saves the next hire from reinventing Pages habits inside App Router folders. Include a one-page “do not” list—common mistakes like fetching in client components for public SEO pages—so code review has a shared standard instead of taste debates.

If your codebase is large or SEO-critical and you want a Senior Developer to lead the sequencing, my Next.js developer services cover migration audits and hands-on delivery. Send your route inventory and constraints via contact, and we can sketch a slice plan that keeps production calm while you move to App Router for real. Bring Search Console access if rankings matter; migration success is measured in continuity, not just green builds.