App Router Routing Basics
Next.js uses a file-system based router. The folder structure inside the app directory directly determines your application routes.
1. Directory and Route Mapping
In the App Router, routes are defined by directories. A route becomes publicly accessible only when you add a page.tsx file inside that directory:
src/app/
├── page.tsx # Homepage (/)
├── about/
│ └── page.tsx # About page (/about)
└── blog/
├── page.tsx # Blog index page (/blog)
└── first-post/
└── page.tsx # Nested post page (/blog/first-post)If a folder does not contain a page.tsx file, it acts purely as a organization folder and will return a 404 error if visited.
2. Layouts and Pages
Two file conventions form the core of Next.js routing:
- page.tsx: Renders the unique UI of a route.
- layout.tsx: Renders shared UI that wraps the current route and all sub-routes nested below it.
Here is how page and layout coordinate:
// src/app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex">
<aside className="w-64 bg-gray-100 p-4">Dashboard Sidebar</aside>
<main className="flex-1 p-8">{children}</main>
</div>
);
}// src/app/dashboard/page.tsx
export default function DashboardPage() {
return <h1>Welcome to your Dashboard overview!</h1>;
}When visiting /dashboard, the page content renders directly inside the layout children parameter placeholder.
3. Nesting Layouts
Layouts nest automatically. The layout declared in /app/layout.tsx serves as the root layout wrapper for the entire site.
If you add a layout in /app/dashboard/layout.tsx, it will wrap the dashboard sub-pages, but will itself render inside the outer root layout. This enables complex nested dashboards with persistent navigation frames.
4. Link-Based Navigation
To navigate between pages, never use standard anchor tags (like a href). Standard anchor tags trigger a full page refresh, discarding React state. Always use the Next.js Link component for client-side navigation:
import Link from "next/link";
export default function Navbar() {
return (
<nav className="flex gap-4">
<Link href="/">Home</Link>
<Link href="/about">About Us</Link>
</nav>
);
}