--- name: nextjs-app-router-fundamentals description: Guide for working with Next.js App Router (Next.js 13+). Use when migrating from Pages Router to App Router, creating layouts, implementing routing, handling metadata, or building Next.js 13+ applications. Activates for App Router migration, layout creation, routing patterns, or Next.js 13+ development tasks. allowed-tools: Read, Write, Edit, Glob, Grep, Bash --- # Next.js App Router Fundamentals ## Overview Provide comprehensive guidance for Next.js App Router (Next.js 13+), covering migration from Pages Router, file-based routing conventions, layouts, metadata handling, and modern Next.js patterns. ## TypeScript: NEVER Use `any` Type **CRITICAL RULE:** This codebase has `@typescript-eslint/no-explicit-any` enabled. Using `any` will cause build failures. **❌ WRONG:** ```typescript function handleSubmit(e: any) { ... } const data: any[] = []; ``` **✅ CORRECT:** ```typescript function handleSubmit(e: React.FormEvent) { ... } const data: string[] = []; ``` ### Common Next.js Type Patterns ```typescript // Page props function Page({ params }: { params: { slug: string } }) { ... } function Page({ searchParams }: { searchParams: { [key: string]: string | string[] | undefined } }) { ... } // Form events const handleSubmit = (e: React.FormEvent) => { ... } const handleChange = (e: React.ChangeEvent) => { ... } // Server actions async function myAction(formData: FormData) { ... } ``` ## When to Use This Skill Use this skill when: - Migrating from Pages Router (`pages/` directory) to App Router (`app/` directory) - Creating Next.js 13+ applications from scratch - Working with layouts, templates, and nested routing - Implementing metadata and SEO optimizations - Building with App Router routing conventions - Handling route groups, parallel routes, or intercepting routes basics ## Core Concepts ### App Router vs Pages Router **Pages Router (Legacy - Next.js 12 and earlier):** ``` pages/ ├── index.tsx # Route: / ├── about.tsx # Route: /about ├── _app.tsx # Custom App component ├── _document.tsx # Custom Document component └── api/ # API routes └── hello.ts # API endpoint: /api/hello ``` **App Router (Modern - Next.js 13+):** ``` app/ ├── layout.tsx # Root layout (required) ├── page.tsx # Route: / ├── about/ # Route: /about │ └── page.tsx ├── blog/ │ ├── layout.tsx # Nested layout │ └── [slug]/ │ └── page.tsx # Dynamic route: /blog/:slug └── api/ # Route handlers └── hello/ └── route.ts # API endpoint: /api/hello ``` ### File Conventions **Special Files in App Router:** - `layout.tsx` - Shared UI for a segment and its children (preserves state, doesn't re-render) - `page.tsx` - Unique UI for a route, makes route publicly accessible - `loading.tsx` - Loading UI with React Suspense - `error.tsx` - Error UI with Error Boundaries - `not-found.tsx` - 404 UI - `template.tsx` - Similar to layout but re-renders on navigation - `route.ts` - API endpoints (Route Handlers) **Colocation:** - Components, tests, and other files can be colocated in `app/` - Only `page.tsx` and `route.ts` files create public routes - Other files (components, utils, tests) are NOT routable ## Migration Guide: Pages Router to App Router ### Step 1: Understand the Current Structure Examine existing Pages Router setup: - Read `pages/` directory structure - Identify `_app.tsx` - handles global state, layouts, providers - Identify `_document.tsx` - customizes HTML structure - Note metadata usage (`next/head`, `` component) - List all routes and dynamic segments ### Step 2: Create Root Layout Create `app/layout.tsx` - **REQUIRED** for all App Router applications: ```typescript // app/layout.tsx export const metadata = { title: 'My App', description: 'App description', }; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {children} ); } ``` **Migration Notes:** - Move `_document.tsx` HTML structure to `layout.tsx` - Move `_app.tsx` global providers/wrappers to `layout.tsx` - Convert `` metadata to `metadata` export - The root layout **MUST** include `` and `` tags ### Step 3: Migrate Pages to Routes **Simple Page Migration:** ```typescript // Before: pages/index.tsx import Head from 'next/head'; export default function Home() { return ( <> Home Page

Welcome

); } ``` ```typescript // After: app/page.tsx export default function Home() { return (

Welcome

); } // Metadata moved to layout.tsx or exported here export const metadata = { title: 'Home Page', }; ``` **Nested Route Migration:** ```typescript // Before: pages/blog/[slug].tsx export default function BlogPost() { ... } ``` ```typescript // After: app/blog/[slug]/page.tsx export default function BlogPost() { ... } ``` ### Step 4: Update Navigation Replace anchor tags with Next.js Link: ```typescript // Before (incorrect in App Router) About // After (correct) import Link from 'next/link'; About ``` ### Step 5: Clean Up Pages Directory After migration: - Remove all page files from `pages/` directory - Keep `pages/api/` if you're not migrating API routes yet - Remove `_app.tsx` and `_document.tsx` (functionality moved to layout) - Optionally delete empty `pages/` directory ## Metadata Handling ### Static Metadata ```typescript // app/page.tsx or app/layout.tsx import type { Metadata } from 'next'; export const metadata: Metadata = { title: 'My Page', description: 'Page description', keywords: ['nextjs', 'react'], openGraph: { title: 'My Page', description: 'Page description', images: ['/og-image.jpg'], }, }; ``` ### Dynamic Metadata ```typescript // app/blog/[slug]/page.tsx export async function generateMetadata({ params }: { params: { slug: string } }): Promise { const post = await getPost(params.slug); return { title: post.title, description: post.excerpt, }; } ``` ## Layouts and Nesting ### Creating Nested Layouts ```typescript // app/layout.tsx - Root layout export default function RootLayout({ children }) { return (
{children}