nextjs-app-router
3
总安装量
3
周安装量
#61619
全站排名
安装命令
npx skills add https://github.com/jawwad-ali/claude-code-skills --skill nextjs-app-router
Agent 安装分布
opencode
3
gemini-cli
3
github-copilot
3
codex
3
kimi-cli
3
cursor
3
Skill 文档
Next.js App Router Development Guide
This skill provides comprehensive guidance for building Next.js applications using the App Router (app directory).
Core Concepts
File-Based Routing
The App Router uses a file-system based router where:
- Folders define routes
- Files define UI for route segments
Special files:
| File | Purpose |
|---|---|
page.tsx |
Unique UI for a route (makes route publicly accessible) |
layout.tsx |
Shared UI for a segment and its children |
loading.tsx |
Loading UI (uses React Suspense) |
error.tsx |
Error UI (uses React Error Boundary) |
not-found.tsx |
Not found UI |
route.ts |
API endpoint (Route Handler) |
template.tsx |
Re-rendered layout |
default.tsx |
Fallback for parallel routes |
Server Components vs Client Components
Server Components (Default)
- All components in
app/are Server Components by default - Can directly access backend resources (database, file system)
- Can use
async/awaitat component level - Cannot use hooks, browser APIs, or event handlers
Client Components
- Add
'use client'directive at the top of the file - Required for interactivity, hooks, browser APIs
- Should be pushed down the component tree
// Server Component (default)
export default async function Page() {
const data = await fetchData() // Direct data fetching
return <div>{data.title}</div>
}
'use client'
// Client Component
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>{count}</button>
}
Data Fetching Patterns
In Server Components (Recommended)
async function getData() {
const res = await fetch('https://api.example.com/data', {
cache: 'force-cache', // default - caches indefinitely
// cache: 'no-store', // never cache
// next: { revalidate: 3600 }, // revalidate every hour
})
return res.json()
}
export default async function Page() {
const data = await getData()
return <main>{data.content}</main>
}
Server Actions (for mutations)
// app/actions.ts
'use server'
export async function createItem(formData: FormData) {
const name = formData.get('name')
await db.items.create({ data: { name } })
revalidatePath('/items')
}
Routing Hooks (Client Components Only)
Import from next/navigation:
'use client'
import { useRouter, usePathname, useSearchParams, useParams } from 'next/navigation'
export function Navigation() {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()
const params = useParams()
// router.push('/dashboard')
// router.replace('/login')
// router.refresh()
// router.back()
// router.forward()
}
Dynamic Routes
app/
âââ blog/
â âââ [slug]/ # Dynamic segment
â âââ page.tsx
âââ shop/
â âââ [...slug]/ # Catch-all segment
â âââ page.tsx
âââ docs/
âââ [[...slug]]/ # Optional catch-all
âââ page.tsx
// app/blog/[slug]/page.tsx
export default async function Page({
params
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
return <article>Post: {slug}</article>
}
// Generate static paths
export async function generateStaticParams() {
const posts = await getPosts()
return posts.map((post) => ({ slug: post.slug }))
}
Layouts and Templates
Root Layout (Required)
// app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Nested Layouts
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<section>
<nav>Dashboard Nav</nav>
{children}
</section>
)
}
Loading and Error States
// app/dashboard/loading.tsx
export default function Loading() {
return <div>Loading...</div>
}
// app/dashboard/error.tsx
'use client'
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</div>
)
}
Route Handlers (API Routes)
// app/api/items/route.ts
import { NextRequest, NextResponse } from 'next/server'
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams
const query = searchParams.get('query')
const items = await getItems(query)
return NextResponse.json(items)
}
export async function POST(request: NextRequest) {
const body = await request.json()
const item = await createItem(body)
return NextResponse.json(item, { status: 201 })
}
Metadata
// Static metadata
export const metadata = {
title: 'My Page',
description: 'Page description',
}
// Dynamic metadata
export async function generateMetadata({ params }) {
const post = await getPost(params.slug)
return {
title: post.title,
description: post.excerpt,
}
}
Best Practices
- Keep Client Components small – Push
'use client'as far down the tree as possible - Colocate data fetching – Fetch data in Server Components close to where it’s used
- Use Server Actions for mutations instead of API routes when possible
- Leverage caching – Use appropriate fetch cache options
- Handle loading/error states – Always provide loading.tsx and error.tsx
- Use route groups
(folder)for organization without affecting URL - Implement parallel routes
@folderfor complex layouts - Use intercepting routes
(.)folderfor modals
Common Patterns
See the references/ directory for detailed patterns:
routing.md– Advanced routing patternsserver-components.md– Server component patternsdata-fetching.md– Data fetching strategies
See the examples/ directory for working code:
page-layout.tsx– Page and layout examplesserver-action.ts– Server action examplesroute-handler.ts– API route examples