Technology · Next.js
Next.js App Router
Master file-based routing with the App Router for modern Next.js apps.
TL;DR
- 01Create routes by organizing files in the app folder structure.
- 02Each page.tsx or page.jsx file becomes a route automatically.
- 03Use brackets [param] for dynamic routes like /blog/[slug].
Basic Routing
- Create pages by adding folders and page.tsx files.
app/ page.tsx # / route about/page.tsx # /about route blog/page.tsx # /blog route - Each folder represents a path segment in the URL.
- Rename page.tsx files to match your naming convention.
- Export a default React component from each page file.
// app/about/page.tsx export default function About() { return <h1>About Us</h1>; } - Use async functions in pages to fetch data on the server.
// app/blog/page.tsx export default async function Blog() { const posts = await getPosts(); return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>; }
Dynamic Routes
- Create dynamic routes with bracket syntax [param].
app/ blog/ [slug]/ page.tsx # /blog/:slug route - Access dynamic parameters in components.
export default function BlogPost({ params }) { return <h1>Post: {params.slug}</h1>; } - Use multiple dynamic segments for nested routes.
app/ users/[id]/posts/[postId]/page.tsx # /users/:id/posts/:postId - Generate static pages from dynamic params with generateStaticParams.
export async function generateStaticParams() { const posts = await getPosts(); return posts.map(p => ({ slug: p.slug })); } - Use notFound() to return a 404 when a resource is missing.
import { notFound } from "next/navigation"; export default async function Post({ params }) { const post = await getPost(params.slug); if (!post) notFound(); return <article>{post.content}</article>; }
Layouts
- Create shared layouts with layout.tsx files.
// app/layout.tsx export default function RootLayout({ children }) { return ( <html> <body> <Header /> {children} <Footer /> </body> </html> ); } - Each folder can have its own layout.
// app/blog/layout.tsx export default function BlogLayout({ children }) { return ( <div> <Sidebar /> {children} </div> ); } - Nested layouts wrap their children.
- Root layout must include html and body tags.
// app/layout.tsx — required at the root export default function RootLayout({ children }) { return ( <html lang="en"> <body>{children}</body> </html> ); } - Export metadata from a layout to share across child pages.
export const metadata = { title: "My Blog", description: "Posts about web development" };
Special Files
- Use error.tsx for error boundaries.
// app/blog/error.tsx export default function Error({ error, reset }) { return ( <div> <h2>Error loading blog</h2> <button onClick={() => reset()}>Try again</button> </div> ); } - Use loading.tsx for Suspense fallbacks.
// app/blog/loading.tsx export default function Loading() { return <p>Loading posts...</p>; } - Use not-found.tsx for 404 pages.
// app/blog/[slug]/not-found.tsx export default function NotFound() { return <h1>Post not found</h1>; } - Use template.tsx for re-mounting a layout on navigation.
// app/blog/template.tsx export default function Template({ children }) { return <div>{children}</div>; // Remounts on each navigation } - Use route.ts files to define API handlers inside the app router.
// app/api/hello/route.ts export async function GET() { return Response.json({ message: "Hello" }); }
Advanced Patterns
- Group routes with parentheses (don't affect URL).
app/ (marketing)/ page.tsx # / (still at root) about/page.tsx # /about (dashboard)/ layout.tsx page.tsx # /dashboard - Create catch-all routes with [...slug].
app/ docs/[...slug]/page.tsx # /docs/a/b/c - Use optional catch-all [[...slug]].
app/ docs/[[...slug]]/page.tsx # Matches /docs, /docs/a, /docs/a/b/c - Use parallel routes with @ to render multiple pages simultaneously.
app/ @analytics/ page.tsx @team/ page.tsx layout.tsx # Receives both slots as props - Use intercepting routes to show modals without full navigation.
app/ photos/ [id]/ page.tsx # /photos/42 — full page (.)photos/ [id]/ page.tsx # intercepted modal view
Tip: Use route groups (parentheses) to organize routes without affecting URLs — great for separating marketing and app sections.
Warning: Avoid deeply nested folder structures — keep routes 3–4 levels deep for clarity and maintainability.