Anna University Plus
Next.js App Router vs Pages Router: A Detailed Comparison Guide - Printable Version

+- Anna University Plus (https://annauniversityplus.com)
+-- Forum: Front-End JavaScript (https://annauniversityplus.com/Forum-front-end-javascript)
+--- Forum: React / Next.js / Vue (https://annauniversityplus.com/Forum-react-next-js-vue)
+--- Thread: Next.js App Router vs Pages Router: A Detailed Comparison Guide (/next-js-app-router-vs-pages-router-a-detailed-comparison-guide)



Next.js App Router vs Pages Router: A Detailed Comparison Guide - Admin - 04-01-2026

Next.js introduced the App Router in version 13, offering a completely new paradigm alongside the traditional Pages Router. This thread compares both approaches to help you choose the right one.

Pages Router (Traditional)

The Pages Router has been the default since Next.js was created. It uses file-based routing under the pages/ directory.

Code:

// pages/about.js
export default function About() {
  return <h1>About Page</h1>;
}
// pages/blog/[slug].js
export async function getStaticProps({ params }) {
  const post = await getPost(params.slug);
  return { props: { post } };
}
export async function getStaticPaths() {
  const posts = await getAllPosts();
  return {
    paths: posts.map(p => ({ params: { slug: p.slug } })),
    fallback: false
  };
}
export default function BlogPost({ post }) {
  return <article>{post.title}</article>;
}

App Router (New)

The App Router uses the app/ directory with a new file convention using page.tsx, layout.tsx, loading.tsx, and error.tsx.

Code:

// app/about/page.tsx
export default function About() {
  return <h1>About Page</h1>;
}
// app/blog/[slug]/page.tsx
export default async function BlogPost({ params }) {
  const post = await getPost(params.slug);
  return <article>{post.title}</article>;
}
// app/blog/[slug]/loading.tsx
export default function Loading() {
  return <div>Loading post...</div>;
}
// app/blog/[slug]/error.tsx
'use client';
export default function Error({ error, reset }) {
  return <button onClick={reset}>Try Again</button>;
}

Key Differences

| Feature | Pages Router | App Router |
|---------|-------------|------------|
| Directory | pages/ | app/ |
| Data Fetching | getServerSideProps, getStaticProps | async Server Components |
| Layouts | Manual _app.js, _document.js | Nested layout.tsx files |
| Loading States | Manual implementation | loading.tsx convention |
| Error Handling | Custom error pages | error.tsx per route |
| Server Components | Not supported | Default behavior |
| Streaming | Limited | Full support |
| Caching | ISR with revalidate | Extended fetch caching |

Layouts in App Router

Code:

// app/layout.tsx (Root Layout)
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <nav>Global Nav</nav>
        {children}
      </body>
    </html>
  );
}
// app/dashboard/layout.tsx (Nested Layout)
export default function DashboardLayout({ children }) {
  return (
    <div className="dashboard">
      <aside>Sidebar</aside>
      <main>{children}</main>
    </div>
  );
}

Data Fetching Comparison

Pages Router requires specific export functions. App Router uses async components directly:

Code:

// App Router - much simpler
async function ProductPage({ params }) {
  const product = await fetch(`/api/products/${params.id}`);
  const data = await product.json();
  return <div>{data.name}</div>;
}

When to Use Which?

- Use Pages Router if you have an existing Next.js project and migration is risky
- Use App Router for new projects to leverage Server Components and streaming
- App Router is the recommended approach going forward
- Pages Router is still fully supported and not deprecated

Migration Strategy

1. Both routers can coexist in the same project
2. Migrate page by page from pages/ to app/
3. Start with simpler pages first
4. Convert data fetching from getServerSideProps to async components
5. Implement layouts to replace repeated _app.js logic

Which router are you using in your projects? Share below!