Next.js App Router patterns — route structure, layouts, server vs client components, dynamic routes, loading/error states, metadata, and navigation. Use when building or modifying routing.
app/ directory).page.tsx.app/ in src/components/.app/
├── layout.tsx # Root layout
├── page.tsx # Home /
├── (auth)/
│ ├── login/page.tsx # /login
│ └── register/page.tsx # /register
├── (main)/
│ ├── layout.tsx # Shared layout for main pages
│ ├── dashboard/page.tsx # /dashboard
│ └── settings/page.tsx # /settings
└── profile/
└── [userId]/page.tsx # /profile/:userId
layout.tsx for shared UI that persists across child routes (nav, sidebar, footer).<html> and <body>.(groupName) to share layouts without affecting URL.'use client' only when needed.'use client' boundary as low as possible in the component tree.'use client' unless absolutely required.[param] for dynamic segments.[...slug] for catch-all routes.[[...slug]] for optional catch-all.type ProfilePageProps = {
params: Promise<{ userId: string }>
}
export const ProfilePage = async ({ params }: ProfilePageProps) => {
const { userId } = await params
}
loading.tsx for route-level Suspense fallback.error.tsx for route-level error boundary (must be 'use client').not-found.tsx for 404 pages.metadata object or generateMetadata function from page.tsx and layout.tsx.title and description.generateMetadata when metadata depends on dynamic params.export const generateMetadata = async ({ params }: ProfilePageProps): Promise<Metadata> => {
const { userId } = await params
return {
title: `Profile ${userId}`,
description: `User profile page`,
}
}
<Link> from next/link for all internal navigation.useRouter() from next/navigation for programmatic navigation.<Link> - do not disable unless justified.redirect() in Server Components for server-side redirects.useRouter().replace() after auth flow (no back to login).pages/ directory - App Router only.