Next.js 16 App Router
SKILL.md
Skill: nextjs
Scope
- Applies to: Next.js 16 App Router - Server Components, Client Components, API routes, Server Actions, middleware, caching
- Does NOT cover: Pages Router, deployment specifics, framework internals
Assumptions
- Next.js 16+
- Node.js 20.9+
- TypeScript 5.1+
- React 19+ (for full feature support)
- Turbopack (stable, default bundler)
Principles
- Use Server Components by default (async/await directly in components)
- Use Client Components (
'use client') only for interactivity (hooks, event handlers) - Use Server Actions for mutations (
'use server') - Use
use cachedirective for explicit component-level caching (Next.js 16) - Use
revalidatePathandrevalidateTagfor cache invalidation - Use Suspense boundaries for async data loading
- Use
useTransitionfor non-urgent updates - Use
useDeferredValuefor deferring expensive computations - Route handlers use
route.tsfiles with named exports (GET,POST, etc.)
Constraints
MUST
- Use Server Components by default (no
'use client'unless needed) - Mark Server Actions with
'use server'directive - Use
revalidatePathorrevalidateTagafter mutations - Handle
searchParamsas Promise in Server Components (Next.js 15+)
SHOULD
- Use
useTransitionfor heavy updates that shouldn't block UI - Use
useDeferredValuewithuseMemoonly for expensive operations (1000+ items) - Use Suspense boundaries for progressive loading
- Use route groups
(group)for organization without affecting URLs
AVOID
- Unnecessary
useMemo/useCallback(React 19 handles most optimizations) - Client Components for static content
- Mixing Server and Client Component patterns incorrectly
- React Compiler (wait for better ecosystem support)
Interactions
- Works with drizzle-orm for database access
- Complements ai-sdk-ui for chat interfaces
- Uses typescript for type safety
Patterns
Server Component
// app/page.tsx
export default async function Page() {
const data = await fetchData()
return <div>{data}</div>
}
Client Component
'use client'
import { useState } from 'react'
export function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>{count}</button>
}
Server Action
'use server'
import { revalidatePath } from 'next/cache'
export async function createItem(formData: FormData) {
await createItemInDB(formData)
revalidatePath('/items')
}
Route Handler
// app/api/items/route.ts
export async function GET() {
return Response.json({ items: [] })
}
export async function POST(request: Request) {
const data = await request.json()
return Response.json({ created: data })
}
Caching
'use cache'
export async function CachedComponent() {
const data = await fetchData() // Cached at component level
return <div>{data}</div>
}
References
- Next.js Documentation - Complete App Router guide
- React Server Components - Server Component patterns