Verified migration

    Next.js Pages Router → App Router, verified by the real compiler.

    Refactyl migrates a Next.js Pages Router project to the App Router, targeting Next 14, the stable production target. pages/ maps to app/ deterministically. _app.tsx and _document.tsx merge into a single root layout. Every converted file passes an App Router lint gate and a real next build before handoff.

    No credit card · Docker-sandboxed · Deleted on handoff · How we handle your code →

    Why this migration is hard to get right

    Data-fetching APIs are replaced, not renamed

    getServerSideProps, getStaticProps, and getInitialProps don't exist in the App Router. The equivalent is an async server component that fetches directly. Converting these patterns correctly requires understanding which data is needed per-request vs. statically, and placing 'use client' boundaries correctly so server-only logic never ships to the browser.

    _app.tsx and _document.tsx collapse into one layout

    Every Pages Router project has a _app and often a _document. The App Router replaces both with a single app/layout.tsx. Merging them (preserving global styles, providers, and <head> setup) requires a coordinated LLM call that reads both files simultaneously. A missing root layout is a build error.

    The App Router lint rules are unforgiving

    No next/router import in Server Components. No next/head or next/document. Exactly one default export per page or layout. Page default exports may only destructure { params, searchParams }, nothing else. The compiler doesn't always explain these clearly; a build that crashes for the wrong reason stalls a migration for hours.

    How Refactyl does it

    01Isolate
    02Plan
    03Transform
    04Verify & Repair

    Path mapping is deterministic: toAppRouterPath converts pages/* to app/* with correct segment brackets (pages/[id].tsx → app/[id]/page.tsx). _app and _document are merged into app/layout.tsx via a single memoized LLM call; a minimal deterministic fallback layout is emitted if generation fails (a missing root layout is a build error). Converted files pass a deterministic App Router lint before acceptance: no pages-era data exports, no next/router|head|document imports, exactly one export default. Unconvertible pages keep their pages/ originals so they remain routable while the rest of the app runs on the App Router.

    Compiler: next build · Zero files ship unverified.

    Before (Pages Router)
    // pages/users/[id].tsx
    import { GetServerSideProps } from 'next'
    
    interface Props { user: { id: string; name: string } }
    
    export const getServerSideProps: GetServerSideProps = async ({ params }) => {
      const user = await fetchUser(params!.id as string)
      return { props: { user } }
    }
    
    export default function UserPage({ user }: Props) {
      return <h1>{user.name}</h1>
    }
    After (App Router, next build verified)
    // app/users/[id]/page.tsx
    interface Props { params: { id: string } }
    
    export default async function UserPage({ params }: Props) {
      const user = await fetchUser(params.id)
      return <h1>{user.name}</h1>
    }

    How to verify the quality claim

    Benchmark

    We haven't published a Next.js Pages RouterApp Router benchmark yet. Until we do, you can verify the quality claim in two ways: the JS→TS benchmark shows how the same verify-and-repair pipeline performs against alternatives on real OSS repos. And the migration audit trail on every run shows exactly which files verified, which were repaired, and which were flagged rather than guessed on, so you can judge the output before downloading anything.

    Manual / official codemod vs Refactyl

    ConcernManual / official codemodRefactyl
    Build gate on handoffYou run next build; errors are your problemnext build passes before you see the diff, or page is flagged
    _app + _document mergeManual: read both, write layout.tsx, test providers still workMemoized LLM merge + deterministic fallback if generation fails
    App Router lint rulesDiscover violations at next build timeDeterministic lint gate catches violations before build
    'use client' placementEasy to misplace: either too broad or missingPer-file analysis: placed at the lowest correct boundary
    Unconvertible pagesSilently broken or blocked until manually resolvedpages/ originals preserved; routable alongside app/ pages
    Target Next versionCodemods target latest, may hit Next 15 async-API surfaceDeliberately targets Next 14, the stable synchronous-params target

    FAQ

    Next.js Pages Router → App Router migration: common questions

    Real questions engineers ask before migrating Next.js Pages Router to App Router, answered honestly.

    Ready to migrate?

    Run your Next.js Pages Router repo through the real compiler.

    One free migration per month, up to 100 files. No credit card. Every file gated by next build, repaired until clean, or clearly flagged with the reason.

    Start free migration

    No credit card · Docker-sandboxed · Deleted on handoff · Never used for training