Getting Started with Next.js App Router

An introduction to the Next.js App Router — understanding server components, layouts, dynamic routes, and how it changes the way we build React applications.

10 February 20262 min read
nextjsreactapp-routerssr

Why App Router?

The Next.js App Router is a paradigm shift from the Pages Router. It embraces React Server Components by default, giving us:

  • Better performance — Less JavaScript shipped to the client
  • Simplified data fetching — No more getServerSideProps or getStaticProps
  • Nested layouts — Share UI between routes without re-rendering

Server vs Client Components

The biggest mental model change is understanding when to use each:

// This is a Server Component by default
// It runs on the server and sends HTML to the client
export default function BlogPost({ params }) {
  const post = getPostBySlug(params.slug);
  return <article>{post.content}</article>;
}
// Add 'use client' for interactive components
'use client';

import { useState } from 'react';

export default function LikeButton() {
  const [likes, setLikes] = useState(0);
  return (
    <button onClick={() => setLikes(l => l + 1)}>
      ❤️ {likes}
    </button>
  );
}

The Layout System

Layouts are one of the best features. They wrap child routes and persist across navigation:

app/
├── layout.js        ← Root layout (wraps everything)
├── page.js          ← Home page
└── blog/
    ├── layout.js    ← Blog layout (sidebar, etc.)
    └── [slug]/
        └── page.js  ← Individual blog post

The root layout only renders once. When you navigate between blog posts, only the inner content changes — the navbar, sidebar, and theme stay mounted.

Dynamic Routes

Dynamic segments are defined with square brackets:

// app/blog/[slug]/page.js
export default function BlogPost({ params }) {
  return <h1>Post: {params.slug}</h1>;
}

// Generate all possible routes at build time
export function generateStaticParams() {
  return posts.map(post => ({ slug: post.slug }));
}

This gives you the best of both worlds: static generation for performance, dynamic URLs for content.

Key Takeaways

  1. Default to Server Components — Only add 'use client' when you need interactivity
  2. Use layouts for shared UI that persists across navigation
  3. Fetch data at the component level — No more prop drilling from page-level data fetchers
  4. Think in terms of streaming — The App Router can stream UI progressively

The App Router is the future of Next.js, and honestly, once you get the mental model, it's more intuitive than the Pages Router ever was.