Why the App Router Exists
The Pages Router (pages/ directory) was Next.js's original routing system. The App Router (app/ directory), introduced in Next.js 13 and stable since Next.js 14, is a complete architectural rethink built on React Server Components.
Core Differences
| Feature | Pages Router | App Router |
|---|---|---|
| Data fetching | getServerSideProps, getStaticProps |
async/await in components |
| Layouts | Manual _app.tsx wrapping |
Nested layout.tsx files |
| Loading states | Manual | loading.tsx with Suspense |
| Error handling | Custom _error.tsx |
error.tsx per segment |
| Components | All client by default | Server by default |
| Streaming | Not supported | Built-in with Suspense |
Pages Router Pattern
// pages/blog/[slug].tsx (old way)
export async function getServerSideProps({ params }) {
const post = await fetchPost(params.slug);
return { props: { post } };
}
export default function BlogPost({ post }) {
return <article>{post.title}</article>;
}
App Router Pattern
// app/blog/[slug]/page.tsx (new way)
async function getPost(slug: string) {
const res = await fetch(`https://api.example.com/posts/${slug}`);
return res.json();
}
export default async function BlogPost({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = await getPost(slug);
return <article>{post.title}</article>;
}
The App Router approach is simpler — data fetching is just async/await inside the component. No special lifecycle functions to learn.
Gradual Migration
You can use both routers simultaneously. The pages/ router takes precedence over conflicting app/ routes, making incremental migration safe:
my-app/
├── app/ # New routes using App Router
│ └── dashboard/
│ └── page.tsx
└── pages/ # Legacy routes still working
└── blog/
└── [slug].tsx
Most new projects should use the App Router exclusively. The Pages Router receives bug fixes but not new features.