The app router: file system as route table

In the Next.js App Router, the file system is the router. A folder becomes a URL segment. A page.tsx inside a folder becomes the page for that URL. No route configuration file, no Router component, just files and folders.

app/
text
app/
├── layout.tsx           # root layout, wraps every page
├── page.tsx             # /
├── books/
│   ├── page.tsx         # /books
│   └── [id]/
│       └── page.tsx     # /books/42
├── login/
│   └── page.tsx         # /login
└── api/
    └── health/
        └── route.ts     # GET /api/health

A minimal App Router layout for a bookstore.

app/books/[id]/page.tsx
tsx
interface PageProps {
  params: { id: string };
}

export default async function BookPage({ params }: PageProps) {
  const res = await fetch('http://localhost:3000/api/books/' + params.id);
  const book = await res.json();

  return (
    <main>
      <h1>{book.title}</h1>
      <p>by {book.author}</p>
    </main>
  );
}

A dynamic route page. The params are passed in as a prop.

Two details to notice. First, the page component is async. In the App Router you can await data directly inside the component, something that was impossible in pure React. Second, the fetch runs on the server, not the client. The resulting HTML is sent to the browser already populated with the book data.

Quiz: Quiz

Loading practice…