# Next.js App Router: A Beginner's Guide to the Core Concepts

> A clear beginner's introduction to the Next.js App Router — what it is, how file-based routing works, and the mental model you need before writing your first page.

- **Published:** 2026-01-13
- **Author:** Clixo
- **Reading time:** 6 min read
- **Tags:** next.js, app-router, beginners, routing, getting-started
- **Canonical URL:** https://clixo.sh/blog/nextjs-app-router-beginners-guide

If you've been building with Next.js for a while, you probably started with the Pages Router — a folder of files that mapped cleanly to URLs. The App Router, introduced in Next.js 13 and now the default, looks similar on the surface but operates on a fundamentally different model. If you're new to Next.js entirely, you may have read the documentation and come away with a list of file names but no clear picture of why the system works the way it does.

This guide focuses on the mental model. Get that right, and the file conventions will make sense on their own.

## What the App Router Actually Is

The App Router is a React application framework built on top of React Server Components. It handles routing through a file system convention, and it renders pages by mixing server and client components together — with server components as the default.

The key shift from the Pages Router: in the Pages Router, you exported React components from files and Next.js rendered them on the server for you. In the App Router, **React Server Components are the runtime**, and the routing conventions are the way you organize them.

## The `app` Directory

All App Router code lives in the `app` directory at the project root. The folder structure defines your URL structure.

```
app/
  page.tsx          → /
  about/
    page.tsx        → /about
  blog/
    page.tsx        → /blog
    [slug]/
      page.tsx      → /blog/any-slug-here
```

Square brackets in folder names create dynamic segments. The value inside the brackets becomes a parameter your page can read.

## The Special Files

Five file names have meaning in the App Router. Understanding what each one does is the foundation of everything else.

**`page.tsx`** — This is the content for a route. Only files named `page.tsx` (or `page.js`) make a route publicly accessible. Other files in the same folder — components, utilities, styles — are colocated but not exposed as routes.

**`layout.tsx`** — This is a wrapper that wraps the page and stays mounted as users navigate between routes in the same section. A layout at `app/dashboard/layout.tsx` wraps every page under `/dashboard/*`. The root layout at `app/layout.tsx` wraps everything, including the `html` and `body` tags.

**`loading.tsx`** — This shows while the page's data is loading. Next.js wraps the page in a `Suspense` boundary automatically when this file exists. You see the loading state immediately and the real page when data is ready.

**`error.tsx`** — This shows when the page throws an error. It replaces the broken page with a recovery UI. You can read the error and offer a retry button.

**`not-found.tsx`** — This shows when you call `notFound()` from within a page, or when no route matches a URL.

Each of these files can exist at any level of the folder hierarchy. Layouts, loading states, and error boundaries nest and apply only to their segment and its children.

```mermaid
flowchart TD
  A["Incoming request"] --> B["layout.tsx wraps segment"]
  B --> C{"Data still loading?"}
  C -- Yes --> D["loading.tsx shown to user"]
  C -- No --> E["page.tsx renders content"]
  E --> F{"Error thrown?"}
  F -- Yes --> G["error.tsx shown with recovery UI"]
  F -- No --> H["HTML streamed to browser"]
  D --> E
```

## Pages Are Server Components by Default

This is the key concept that trips up most beginners. When you write a `page.tsx` file, it is a React Server Component unless you explicitly mark it otherwise. That means:

- It runs on the server, not in the browser
- It can `await` database queries or API calls directly in the component body
- It never ships its own JavaScript to the client
- It cannot use `useState`, `useEffect`, or any browser API

If you need interactivity — a button that toggles a menu, a form with controlled inputs — you create a separate component file, add `'use client'` at the top, and import it into your page. That client component is the only part of the page that ships JavaScript to the browser.

## A Simple Page in Practice

Here is a blog post page that fetches its content from a database:

```typescript
// app/blog/[slug]/page.tsx
import { notFound } from 'next/navigation'
import { getPostBySlug } from '@/lib/db'

export default async function BlogPostPage({
  params,
}: {
  params: { slug: string }
}) {
  const post = await getPostBySlug(params.slug)

  if (!post) notFound()

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.publishedAt}</p>
      <div>{post.content}</div>
    </article>
  )
}
```

This component runs on the server. It queries the database directly. It returns HTML. No client-side JavaScript is involved.

## Navigation

Use the `Link` component from `next/link` for internal navigation. It handles prefetching automatically and works without JavaScript when needed.

```typescript
import Link from 'next/link'

export function NavBar() {
  return (
    <nav>
      <Link href="/">Home</Link>
      <Link href="/blog">Blog</Link>
    </nav>
  )
}
```

For programmatic navigation — redirecting after a form submission — use `redirect()` from `next/navigation` inside a server component or Server Action, or `useRouter()` inside a client component.

## Route Groups

Sometimes you want shared layouts for a group of routes without affecting the URL. Route groups are folders wrapped in parentheses:

```
app/
  (marketing)/
    layout.tsx     ← shared marketing layout
    page.tsx       → /
    about/
      page.tsx     → /about
  (dashboard)/
    layout.tsx     ← shared dashboard layout
    settings/
      page.tsx     → /settings
```

The `(marketing)` and `(dashboard)` folder names do not appear in the URL. They exist purely to organize layouts.

## What to Learn Next

Once the mental model clicks, the natural next steps are:

1. Data fetching patterns — parallel fetches, Suspense streaming, caching
2. Server Actions — how to handle form submissions and mutations without API routes
3. Middleware — how to run code before a request reaches a page (authentication, redirects)
4. Metadata API — how to set `title` and `description` per page for SEO

The App Router has a learning curve, but it is a coherent system. Each feature builds on the same foundation: server components are the default, client components are the exception, and the file system is the router.

If you're a product team looking to build on Next.js and want engineers who know the platform deeply, [Clixo is a good starting point](https://clixo.sh/#contact). We design and build full-stack Next.js applications for founders and product organizations.

---

Clixo · 1141 W Bryn Mawr Ave, Itasca, IL 60143, US · [hello@clixo.sh](mailto:hello@clixo.sh)
[Start a build](https://clixo.sh/#contact) · [All services](https://clixo.sh/services) · [Agent guide (llms.txt)](https://clixo.sh/llms.txt)
