Back to Blog

Getting Started with Next.js App Router

A comprehensive guide to building modern web applications with Next.js App Router, including server components, layouts, and dynamic routing.

May 10, 20263 min read
Next.jsReactWeb Development

The Next.js App Router represents a paradigm shift in how we build React applications. Introduced as part of Next.js 13 and continuously refined, it leverages React Server Components to deliver a more intuitive and performant development experience.

Why the App Router?

The App Router is built on top of React Server Components, which allow you to render components on the server without sending JavaScript to the client. This means smaller bundle sizes, faster page loads, and a more straightforward mental model for data fetching.

With the Pages Router, we had to deal with getServerSideProps and getStaticProps for data fetching. The App Router simplifies this by allowing you to fetch data directly inside server components using standard async/await patterns.

File-Based Routing

The App Router uses a file-system based router where folders define routes. Special files like page.tsx, layout.tsx, and loading.tsx give each route segment its own UI and behavior:

app/
  layout.tsx       → Root layout (wraps all pages)
  page.tsx         → Home page (/)
  blog/
    layout.tsx     → Blog layout
    page.tsx       → Blog index (/blog)
    [slug]/
      page.tsx     → Dynamic blog post (/blog/:slug)

This structure makes it immediately clear how your application is organized, and each file has a specific purpose.

Server Components by Default

Every component in the App Router is a Server Component by default. This means they render on the server and don't add to the client-side JavaScript bundle. When you need interactivity, you opt into Client Components with the "use client" directive:

// This is a Server Component (default)
async function BlogList() {
  const posts = await fetchPosts();
  return (
    <ul>
      {posts.map(post => <li key={post.id}>{post.title}</li>)}
    </ul>
  );
}
 
// This is a Client Component
"use client";
function LikeButton() {
  const [likes, setLikes] = useState(0);
  return <button onClick={() => setLikes(l => l + 1)}>Likes: {likes}</button>;
}

Layouts and Templates

Layouts are one of the most powerful features of the App Router. A layout wraps its child routes and persists across navigations, maintaining state. This is perfect for shared navigation, sidebars, or any UI that should remain consistent:

export default function BlogLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="flex">
      <nav className="w-64 border-r">
        {/* Navigation persists */}
      </nav>
      <main className="flex-1">{children}</main>
    </div>
  );
}

Data Fetching Patterns

The App Router supports multiple rendering strategies. You can use Static Site Generation (SSG) for content that doesn't change often, Server-Side Rendering (SSR) for dynamic content, or Incremental Static Regeneration (ISR) for the best of both worlds.

For a blog, SSG is ideal — posts are built at compile time, resulting in lightning-fast page loads. Simply export a generateStaticParams function to pre-render all your blog post pages at build time.

Getting Started

To create a new Next.js project with the App Router, run:

npx create-next-app@latest my-app --typescript --tailwind --app

This scaffolds a complete project with TypeScript, Tailwind CSS, and the App Router enabled by default. From there, you can start building your application by adding pages, layouts, and API routes.

The App Router is the future of Next.js development. It provides a more intuitive API, better performance, and tighter integration with React's latest features. If you're starting a new project, there's no reason not to use it.