Why Use the App Router?
The Pages Router still works, and plenty of production sites run on it. So why is every new Trailhead file going into app? Because the App Router solves real problems the Pages Router could only work around, and new Next.js features land there first.
The rule
Less JavaScript, shared shells, earlier pixels, data where it is used.
Each phrase is one advantage.
Less JavaScript: server components. Components in app run on the server by default. Their code, and the libraries they import (a Markdown parser, a date library, a database client), never reach the browser. Only the parts you mark as client components are shipped. Trailhead's mostly-reading pages stay light.
Shared shells: nested layouts. A layout.tsx wraps its whole subtree and stays mounted during navigation. The header and the trails sidebar are drawn once and keep their state while the page inside changes. The Pages Router had one global _app shell, so per-section shells needed workarounds.
Earlier pixels: streaming. A loading.tsx file or a <Suspense> boundary lets the server send the fast parts of a page first and fill in slow parts as they finish. In the Pages Router, getServerSideProps had to finish completely before anything was sent.
Data where it is used: async components. Any server component can await its own data:
// app/trails/[slug]/page.tsx
export default async function TrailPage({ params }) {
const { slug } = await params;
const trail = await getTrail(slug);
return (
<article>
<h1>{trail.name}</h1>
<Forecast lat={trail.lat} lon={trail.lon} /> {/* fetches its own weather */}
</article>
);
}Forecast can load the weather itself instead of the page loading it and passing it down. In the Pages Router, only the page's get…Props function could load server data.
Also in the App Router: route handlers built on the standard Web Request and Response, and colocation, meaning components, styles and tests can live beside the page that uses them.
The shortcut
When deciding, match each pain to a feature: bundle too big → server components; shared UI flickers → layouts; slow data blocks the page → streaming; data plumbing through props → async components.
Pain: trail pages ship a Markdown library
Server components parse Markdown on the server; the library never ships.
The trap is assuming "App Router" means "everything runs on the server". Client components are still there for anything interactive; you choose where the line sits.
Drills
Answer fast — trust the rule.
Why do App Router pages often ship less JavaScript?
Which App Router feature keeps Trailhead's header mounted while pages change?
A slow forecast should not delay the rest of the trail page. What does the App Router offer?
In the App Router, which components can load server data by awaiting it?
Remember
- Less JavaScript, shared shells, earlier pixels, data where it is used.
- Shortcut: match each pain to a feature.
- Trap: the App Router still has client components; you decide where the boundary goes.
