The App Router vs Pages Router
Next.js has shipped two routing systems over its history. The Pages Router, based on the pages/ directory, was the original system and maps each file to a route using getStaticProps and getServerSideProps for data fetching. The App Router, introduced in Next.js 13 and stabilized in 13.4, uses the app/ directory, is built on React Server Components, and supports nested layouts, streaming, and colocated data fetching with async/await directly inside components.
Cricket analogy: The Pages Router is like Test cricket's traditional format, well-established with fixed rules, while the App Router is like the newer Hundred format, redesigned from first principles with a different structure for a modern audience.
How the Pages Router Works
In the Pages Router, every file under pages/ becomes a route automatically: pages/about.js becomes /about, and pages/index.js becomes /. Data fetching happens through exported functions like getStaticProps (build-time data), getServerSideProps (per-request data), or getStaticPaths (for dynamic routes). Shared UI like a navbar goes in a special _app.js file, and custom document-level HTML structure goes in _document.js.
Cricket analogy: getStaticProps fetching data at build time is like preparing a scorecard template before the toss, while getServerSideProps is like updating the live scoreboard in real time as each ball is bowled during the innings.
How the App Router Works
The App Router uses folders inside app/ where a page.tsx file marks a route as publicly accessible, and layout.tsx files wrap that route and any nested routes beneath it. Components are React Server Components by default, meaning they can be async and fetch data directly with await without needing getServerSideProps. Special files like loading.tsx and error.tsx automatically create loading and error UI boundaries for that route segment.
Cricket analogy: A page.tsx marking a route as accessible is like a player being named in the official playing XI — only then do they actually take the field, even though the whole squad exists in the folder.
// app/layout.tsx (Root layout, required)
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<nav>Site Navigation</nav>
{children}
</body>
</html>
);
}
// app/dashboard/page.tsx (Server Component, async data fetching)
async function getStats() {
const res = await fetch('https://api.example.com/stats', { cache: 'no-store' });
return res.json();
}
export default async function DashboardPage() {
const stats = await getStats();
return <section><h1>Dashboard</h1><p>Active users: {stats.activeUsers}</p></section>;
}Next.js supports incremental adoption: a single project can have both an app/ directory and a pages/ directory at the same time, letting teams migrate route by route instead of rewriting the whole application at once.
Which Should You Choose?
For new projects, the App Router is the recommended default because it unlocks nested layouts, streaming with Suspense, colocated loading and error states, and simpler data fetching without separate lifecycle functions. The Pages Router remains fully supported and is a reasonable choice for maintaining existing applications or when a team relies on ecosystem libraries that assume the Pages Router's data-fetching model.
Cricket analogy: Choosing the App Router for a new project is like a franchise building its squad around T20 specialists from day one, rather than retrofitting Test-match veterans into a format they weren't developed for.
You cannot define the same URL path in both pages/ and app/ simultaneously — Next.js will throw a build error. When migrating incrementally, move one route at a time and be aware that data-fetching patterns differ significantly: getServerSideProps has no direct App Router equivalent, since data fetching happens via async Server Components instead.
- The Pages Router uses pages/ with getStaticProps/getServerSideProps for data fetching.
- The App Router uses app/ and is built on React Server Components.
- App Router supports nested layouts, streaming, and colocated async data fetching.
- Both routers can coexist in the same project for incremental migration.
- The same URL path cannot be defined in both routers at once.
- App Router is the recommended default for new Next.js projects.
- Pages Router remains fully supported for existing applications.
Practice what you learned
1. Which Next.js version introduced the App Router?
2. What are components inside the app/ directory by default?
3. Which file in the App Router marks a folder as a publicly accessible route?
4. What happens if you define the same URL path in both pages/ and app/?
5. In the Pages Router, which function fetches data at build time for static generation?
Was this page helpful?
You May Also Like
What Is Next.js?
An introduction to Next.js, the React framework for production that adds routing, rendering strategies, and full-stack capabilities on top of React.
File-Based Routing
How Next.js derives an application's routes automatically from the folder structure inside the app directory, including dynamic segments and navigation.
Layouts and Nested Routes
How layout.tsx files in the Next.js App Router share UI across routes, compose through nesting, and persist state across navigations.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics