nextjs-routing

star 0

Next.js App Router conventions - route structure, layouts, server vs client components, dynamic routes, loading states, metadata, and navigation.

hzblj By hzblj schedule Updated 2/18/2026

name: nextjs-routing description: Next.js App Router conventions - route structure, layouts, server vs client components, dynamic routes, loading states, metadata, and navigation.

Routing (Next.js App Router)

Structure

  • Use App Router (app/ directory).
  • Every route is a folder with page.tsx.
  • Colocate route-specific components in the route folder.
  • Shared components live outside 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

Layouts

  • Use layout.tsx for shared UI that persists across child routes (nav, sidebar, footer).
  • Layouts do not re-render on route change - use this for expensive components.
  • Root layout must contain <html> and <body>.
  • Use route groups (groupName) to share layouts without affecting URL.
  • Do not nest layouts deeper than necessary - max 3 levels.

Server vs Client Components

  • Default to Server Components. Add 'use client' only when needed.
  • Server Components: data fetching, static content, SEO-critical pages.
  • Client Components: interactivity, event handlers, hooks, browser APIs.
  • Keep 'use client' boundary as low as possible in the component tree.
  • Never mark a layout as 'use client' unless absolutely required.

Dynamic Routes

  • Use [param] for dynamic segments.
  • Use [...slug] for catch-all routes.
  • Use [[...slug]] for optional catch-all.
  • Always validate and type params.
type ProfilePageProps = {
  params: Promise<{ userId: string }>
}

export const ProfilePage = async ({ params }: ProfilePageProps) => {
  const { userId } = await params
}

Loading & Error States

  • Use loading.tsx for route-level Suspense fallback.
  • Use error.tsx for route-level error boundary (must be 'use client').
  • Use not-found.tsx for 404 pages.
  • Keep loading states lightweight - skeleton over spinner.

Metadata

  • Export metadata object or generateMetadata function from page.tsx and layout.tsx.
  • Every page must have title and description.
  • Use 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`,
  }
}

Navigation

  • Use <Link> from next/link for all internal navigation.
  • Use useRouter() from next/navigation for programmatic navigation.
  • Prefetch is automatic for <Link> - do not disable unless justified.
  • Use redirect() in Server Components for server-side redirects.
  • Use useRouter().replace() after auth flow (no back to login).

Rules

  • Never use pages/ directory - App Router only.
  • Do not fetch data in Client Components if it can be done in Server Components.
  • Keep route params serializable (string only from URL).
  • Avoid passing data between routes via query params when server-side fetch is possible.
  • Colocate route logic - do not scatter one route's files across the project.
Install via CLI
npx skills add https://github.com/hzblj/wedding --skill nextjs-routing
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator