Next应用路由
nextjs-app-router
by giuseppe-trisciuoglio
聚焦Next.js16+ App Router,梳理Server Actions、route.ts、use cache和并行/拦截路由,适合项目搭建、文件约定落地与proxy.ts迁移。
安装
claude skill add --url github.com/giuseppe-trisciuoglio/developer-kit/tree/main/plugins/developer-kit-typescript/skills/nextjs-app-router文档
Next.js App Router (Next.js 16+)
Build modern React applications using Next.js 16+ with App Router architecture.
Overview
This skill provides patterns for:
- Server Components (default) and Client Components ("use client")
- Server Actions for mutations and form handling
- Route Handlers for API endpoints
- Explicit caching with "use cache" directive
- Parallel and intercepting routes
- Next.js 16 async APIs and proxy.ts
When to Use
Activate when user requests involve:
- "Create a Next.js 16 project", "Set up App Router"
- "Server Component", "Client Component", "use client"
- "Server Action", "form submission", "mutation"
- "Route Handler", "API endpoint", "route.ts"
- "use cache", "cacheLife", "cacheTag", "revalidation"
- "parallel routes", "@slot", "intercepting routes"
- "proxy.ts", "migrate from middleware.ts"
- "layout.tsx", "page.tsx", "loading.tsx", "error.tsx", "not-found.tsx"
- "generateMetadata", "next/image", "next/font"
Quick Reference
File Conventions
| File | Purpose |
|---|---|
page.tsx | Route page component |
layout.tsx | Shared layout wrapper |
loading.tsx | Suspense loading UI |
error.tsx | Error boundary |
not-found.tsx | 404 page |
template.tsx | Re-mounting layout |
route.ts | API Route Handler |
default.tsx | Parallel route fallback |
proxy.ts | Routing boundary (Next.js 16) |
Directives
| Directive | Purpose |
|---|---|
"use server" | Mark Server Action functions |
"use client" | Mark Client Component boundary |
"use cache" | Enable explicit caching (Next.js 16) |
Instructions
Create New Project
npx create-next-app@latest my-app --typescript --tailwind --app --turbopack
Implement Server Component
Server Components are the default in App Router.
// app/users/page.tsx
async function getUsers() {
const apiUrl = process.env.API_URL;
const res = await fetch(`${apiUrl}/users`);
return res.json();
}
export default async function UsersPage() {
const users = await getUsers();
return (
<main>
{users.map(user => <UserCard key={user.id} user={user} />)}
</main>
);
}
Implement Client Component
Add "use client" when using hooks, browser APIs, or event handlers.
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
}
Create Server Action
Define actions in separate files with "use server" directive.
// app/actions.ts
"use server";
import { revalidatePath } from "next/cache";
export async function createUser(formData: FormData) {
const name = formData.get("name") as string;
const email = formData.get("email") as string;
await db.user.create({ data: { name, email } });
revalidatePath("/users");
}
Use with forms in Client Components:
"use client";
import { useActionState } from "react";
import { createUser } from "./actions";
export default function UserForm() {
const [state, formAction, pending] = useActionState(createUser, {});
return (
<form action={formAction}>
<input name="name" />
<input name="email" type="email" />
<button type="submit" disabled={pending}>
{pending ? "Creating..." : "Create"}
</button>
</form>
);
}
See references/server-actions.md for validation with Zod, optimistic updates, and advanced patterns.
Configure Caching
Use "use cache" directive for explicit caching (Next.js 16+).
"use cache";
import { cacheLife, cacheTag } from "next/cache";
export default async function ProductPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
cacheTag(`product-${id}`);
cacheLife("hours");
const product = await fetchProduct(id);
return <ProductDetail product={product} />;
}
See references/caching-strategies.md for cache profiles, on-demand revalidation, and advanced caching patterns.
Create Route Handler
Implement API endpoints using Route Handlers.
// app/api/users/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest) {
const users = await db.user.findMany();
return NextResponse.json(users);
}
export async function POST(request: NextRequest) {
const body = await request.json();
const user = await db.user.create({ data: body });
return NextResponse.json(user, { status: 201 });
}
Dynamic segments use [param]:
// app/api/users/[id]/route.ts
interface RouteParams {
params: Promise<{ id: string }>;
}
export async function GET(request: NextRequest, { params }: RouteParams) {
const { id } = await params;
const user = await db.user.findUnique({ where: { id } });
if (!user) {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
return NextResponse.json(user);
}
Handle Next.js 16 Async APIs
All Next.js APIs are async in version 16.
import { cookies, headers, draftMode } from "next/headers";
export default async function Page() {
const cookieStore = await cookies();
const headersList = await headers();
const { isEnabled } = await draftMode();
const session = cookieStore.get("session")?.value;
const userAgent = headersList.get("user-agent");
return <div>...</div>;
}
Params and searchParams are also async:
export default async function Page({
params,
searchParams,
}: {
params: Promise<{ slug: string }>;
searchParams: Promise<{ sort?: string }>;
}) {
const { slug } = await params;
const { sort } = await searchParams;
// ...
}
See references/nextjs16-migration.md for migration guide and proxy.ts configuration.
Implement Parallel Routes
Use @folder convention for parallel route slots.
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
team,
analytics,
}: {
children: React.ReactNode;
team: React.ReactNode;
analytics: React.ReactNode;
}) {
return (
<div>
{children}
<div className="grid grid-cols-2">
{team}
{analytics}
</div>
</div>
);
}
// app/dashboard/@team/page.tsx
export default function TeamPage() {
return <div>Team Section</div>;
}
// app/dashboard/@analytics/page.tsx
export default function AnalyticsPage() {
return <div>Analytics Section</div>;
}
See references/routing-patterns.md for intercepting routes, route groups, and dynamic routes.
Best Practices
Server vs Client Decision
- Start with Server Component (default)
- Use Client Component only for:
- React hooks (useState, useEffect, useContext)
- Browser APIs (window, document, localStorage)
- Event handlers (onClick, onSubmit)
- Client-only libraries
Data Fetching
- Fetch in Server Components when possible
- Use React's
cache()for deduplication - Parallelize independent fetches
- Add Suspense boundaries with
loading.tsx
Caching Strategy
"use cache";
import { cacheLife, cacheTag } from "next/cache";
// Set cache duration
cacheLife("hours");
// Tag for revalidation
cacheTag("resource-name");
Performance Checklist
- Use
loading.tsxfor Suspense boundaries - Use
next/imagefor optimized images - Use
next/fontfor font optimization - Enable React Compiler in
next.config.ts - Add
error.tsxfor error handling - Add
not-found.tsxfor 404 handling
Examples
Example 1: Create Blog Post with Server Action
Input: Create a form to submit blog posts with validation
Output:
// app/blog/actions.ts
"use server";
import { z } from "zod";
import { revalidatePath } from "next/cache";
const schema = z.object({
title: z.string().min(5),
content: z.string().min(10),
});
export async function createPost(formData: FormData) {
const parsed = schema.safeParse({
title: formData.get("title"),
content: formData.get("content"),
});
if (!parsed.success) {
return { errors: parsed.error.flatten().fieldErrors };
}
await db.post.create({ data: parsed.data });
revalidatePath("/blog");
return { success: true };
}
// app/blog/new/page.tsx
"use client";
import { useActionState } from "react";
import { createPost } from "../actions";
export default function NewPostPage() {
const [state, formAction, pending] = useActionState(createPost, {});
return (
<form action={formAction}>
<input name="title" placeholder="Title" />
{state.errors?.title && <span>{state.errors.title[0]}</span>}
<textarea name="content" placeholder="Content" />
{state.errors?.content && <span>{state.errors.content[0]}</span>}
<button type="submit" disabled={pending}>
{pending ? "Publishing..." : "Publish"}
</button>
</form>
);
}
Example 2: Product Page with Caching
Input: Create a cached product page with revalidation
Output:
// app/products/[id]/page.tsx
"use cache";
import { cacheLife, cacheTag } from "next/cache";
export default async function ProductPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
cacheTag(`product-${id}`, "products");
cacheLife("hours");
const product = await db.product.findUnique({ where: { id } });
if (!product) {
notFound();
}
return (
<article>
<h1>{product.name}</h1>
<p>{product.description}</p>
<p>${product.price}</p>
</article>
);
}
// app/api/revalidate/route.ts
import { revalidateTag } from "next/cache";
import { NextResponse } from "next/server";
export async function POST(request: Request) {
const { tag } = await request.json();
revalidateTag(tag);
return NextResponse.json({ revalidated: true });
}
Example 3: Dashboard with Parallel Routes
Input: Create a dashboard with sidebar and main content areas
Output:
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
sidebar,
stats,
}: {
children: React.ReactNode;
sidebar: React.ReactNode;
stats: React.ReactNode;
}) {
return (
<div className="flex">
<aside className="w-64">{sidebar}</aside>
<main className="flex-1">
<div className="grid grid-cols-3">{stats}</div>
{children}
</main>
</div>
);
}
// app/dashboard/@sidebar/page.tsx
export default function Sidebar() {
return <nav>{/* Navigation links */}</nav>;
}
// app/dashboard/@stats/page.tsx
export default async function Stats() {
const stats = await fetchStats();
return (
<>
<div>Users: {stats.users}</div>
<div>Orders: {stats.orders}</div>
<div>Revenue: {stats.revenue}</div>
</>
);
}
Constraints and Warnings
Constraints
- Server Components cannot use browser APIs or React hooks
- Client Components cannot be async (no direct data fetching)
cookies(),headers(),draftMode()are async in Next.js 16paramsandsearchParamsare Promise-based in Next.js 16- Server Actions must be defined with "use server" directive
Warnings
- Attempting to use
awaitin a Client Component will cause a build error - Accessing
windowordocumentin Server Components will throw an error - Forgetting to await
cookies()orheaders()in Next.js 16 will result in a Promise instead of the actual values - Server Actions without proper validation can expose your database to unauthorized access
- External Data Fetching: Server Components that fetch data from external APIs (
fetch()calls to third-party URLs) process untrusted content; always validate, sanitize, and type-check fetched responses before rendering, and use environment variables for API URLs rather than hardcoding them
References
Consult these files for detailed patterns:
- references/app-router-fundamentals.md - Server/Client Components, file conventions, navigation, next/image, next/font
- references/routing-patterns.md - Parallel routes, intercepting routes, route groups, dynamic routes
- references/caching-strategies.md - "use cache", cacheLife, cacheTag, revalidation
- references/server-actions.md - Server Actions, useActionState, validation, optimistic updates
- references/nextjs16-migration.md - Async APIs, proxy.ts, Turbopack, config
- references/data-fetching.md - Data patterns, Suspense, streaming
- references/metadata-api.md - generateMetadata, OpenGraph, sitemap
相关 Skills
网页构建器
by anthropics
面向复杂 claude.ai HTML artifact 开发,快速初始化 React + Tailwind CSS + shadcn/ui 项目并打包为单文件 HTML,适合需要状态管理、路由或多组件交互的页面。
✎ 在 claude.ai 里做复杂网页 Artifact 很省心,多组件、状态和路由都能顺手搭起来,React、Tailwind 与 shadcn/ui 组合效率高、成品也更精致。
前端设计
by anthropics
面向组件、页面、海报和 Web 应用开发,按鲜明视觉方向生成可直接落地的前端代码与高质感 UI,适合做 landing page、Dashboard 或美化现有界面,避开千篇一律的 AI 审美。
✎ 想把页面做得既能上线又有设计感,就用前端设计:组件到整站都能产出,难得的是能避开千篇一律的 AI 味。
网页应用测试
by anthropics
用 Playwright 为本地 Web 应用编写自动化测试,支持启动开发服务器、校验前端交互、排查 UI 异常、抓取截图与浏览器日志,适合调试动态页面和回归验证。
✎ 借助 Playwright 一站式验证本地 Web 应用前端功能,调 UI 时还能同步查看日志和截图,定位问题更快。
相关 MCP 服务
GitHub
编辑精选by GitHub
GitHub 是 MCP 官方参考服务器,让 Claude 直接读写你的代码仓库和 Issues。
✎ 这个参考服务器解决了开发者想让 AI 安全访问 GitHub 数据的问题,适合需要自动化代码审查或 Issue 管理的团队。但注意它只是参考实现,生产环境得自己加固安全。
Context7 文档查询
编辑精选by Context7
Context7 是实时拉取最新文档和代码示例的智能助手,让你告别过时资料。
✎ 它能解决开发者查找文档时信息滞后的问题,特别适合快速上手新库或跟进更新。不过,依赖外部源可能导致偶尔的数据延迟,建议结合官方文档使用。
by tldraw
tldraw 是让 AI 助手直接在无限画布上绘图和协作的 MCP 服务器。
✎ 这解决了 AI 只能输出文本、无法视觉化协作的痛点——想象让 Claude 帮你画流程图或白板讨论。最适合需要快速原型设计或头脑风暴的开发者。不过,目前它只是个基础连接器,你得自己搭建画布应用才能发挥全部潜力。