Two routers, one repo — for now
Next.js still ships both routers because legacy apps haven't all migrated. New work belongs in the App Router (app/ directory). The Pages Router (pages/) exists for migration and won't see new feature work.
| Capability | Pages Router | App Router |
|---|---|---|
| Directory | pages/ | app/ |
| Default render target | Client | Server |
| Data fetching | getServerSideProps / getStaticProps | async components, direct fetch |
| Layouts | Manual _app.tsx wrap | layout.tsx per segment |
| Loading UI | Manual | loading.tsx + Suspense |
| Error UI | _error.tsx | error.tsx + global-error.tsx |
| Streaming | Limited | First-class |
| Server Actions | No | Yes |
The mental model shift
Pages Router thinks in pages with separate data-fetching functions. App Router thinks in composable Server & Client Components organized by route segments. Most "Next.js feels weird now" reactions are about this shift, not about syntax.
Coexistence rules
Both routers work in the same project, segment by segment. If a path exists in both app/ and pages/, App Router wins. Migrate route by route; you don't need a big-bang rewrite.