**Version**: Next.js 16.0.3
Generates Next.js 16 App Router code with Server Components, Server Actions, and caching patterns.
npx claudepluginhub secondsky/claude-skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/caching-apis.mdreferences/error-catalog.mdreferences/next-16-migration-guide.mdreferences/server-actions-patterns.mdreferences/top-errors.mdscripts/check-versions.shtemplates/app-router-async-params.tsxtemplates/async-params-page.tsxtemplates/cache-component-use-cache.tsxtemplates/package.jsontemplates/parallel-routes-with-default.tsxtemplates/proxy-migration.tstemplates/route-handler-api.tstemplates/server-action-form.tsxtemplates/server-actions-form.tsxVersion: Next.js 16.0.3 React Version: 19.2.0 Node.js: 20.9+ Last Verified: 2025-11-21
Use this skill when you need:
"use cache" directive (NEW in Next.js 16)revalidateTag(), updateTag(), refresh() (Updated in Next.js 16)proxy.ts replaces middleware.ts in Next.js 16)params, searchParams, cookies(), headers() now async)useEffectEvent(), React Compiler)next/image with updated defaults in Next.js 16)Do NOT use this skill for:
cloudflare-nextjs skill insteadclerk-auth, auth-js, or other auth-specific skillscloudflare-d1, drizzle-orm-d1, or database-specific skillstailwind-v4-shadcn skill for Tailwind + shadcn/uizustand-state-management, tanstack-query skillsreact-hook-form-zod skillCRITICAL: Next.js 16 has multiple breaking changes. For detailed migration steps, see references/next-16-migration-guide.md.
| Breaking Change | Before | After |
|---|---|---|
| Async params | params.slug | const { slug } = await params |
| Async headers | cookies() sync | await cookies() |
| Middleware | middleware.ts | proxy.ts (renamed) |
| Parallel routes | default.js optional | default.js required |
| Caching | Auto-cached fetch | Opt-in with "use cache" |
| revalidateTag() | 1 argument | 2 arguments (tag + cacheLife) |
| Node.js | 18.x+ | 20.9+ required |
| React | 18.x | 19.2+ required |
Quick Fix for Async Params:
// ✅ Next.js 16 pattern
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
return <div>{id}</div>
}
Codemod: bunx @next/codemod@canary upgrade latest
See: references/next-16-migration-guide.md for complete migration guide with examples.
'use cache'
export async function BlogPosts() {
const posts = await db.posts.findMany()
return posts.map(post => <article key={post.id}>{post.title}</article>)
}
| API | Purpose | Example |
|---|---|---|
"use cache" | Opt-in component/function caching | 'use cache' at top |
revalidateTag() | Invalidate by tag | revalidateTag('posts', 'max') |
updateTag() | Update cache without revalidation | updateTag('posts', newData) |
refresh() | Refresh current page | refresh() |
revalidatePath() | Invalidate by path | revalidatePath('/posts') |
// next.config.ts
const config = { experimental: { ppr: true } }
// page.tsx
export const experimental_ppr = true
export default function Page() {
return (
<>
<StaticHeader />
<Suspense fallback={<Skeleton />}>
<DynamicContent />
</Suspense>
</>
)
}
See: references/caching-apis.md for complete caching API reference with ISR, tag-based revalidation, and advanced patterns.
Server Components are the default in App Router. They run on the server and can fetch data, access databases, and keep logic server-side.
// app/posts/page.tsx (Server Component by default)
export default async function PostsPage() {
const posts = await db.posts.findMany()
return <div>{posts.map(p => <article key={p.id}>{p.title}</article>)}</div>
}
import { Suspense } from 'react'
export default function Page() {
return (
<div>
<Header />
<Suspense fallback={<Skeleton />}>
<Posts />
</Suspense>
</div>
)
}
| Server Components | Client Components |
|---|---|
| Data fetching, DB access | Interactivity (onClick) |
| Sensitive logic | React hooks (useState) |
| Large dependencies | Browser APIs |
| Static content | Real-time updates |
Client Component (requires 'use client'):
'use client'
import { useState } from 'react'
export function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>{count}</button>
}
Server Actions are async functions that run on the server, callable from Client or Server Components.
// app/actions.ts
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost(formData: FormData) {
const title = formData.get('title') as string
await db.posts.create({ data: { title } })
revalidatePath('/posts')
}
// Server Component Form (simplest)
import { createPost } from './actions'
export default function NewPostPage() {
return (
<form action={createPost}>
<input name="title" required />
<button type="submit">Create</button>
</form>
)
}
| Pattern | Use Case | Reference |
|---|---|---|
| Client Form with Loading | useFormState + useFormStatus | templates/server-action-form.tsx |
| Error Handling | Return { error } or { success } | references/server-actions-patterns.md |
| Optimistic Updates | useOptimistic hook | references/server-actions-patterns.md |
| File Upload | FormData + blob storage | references/server-actions-patterns.md |
| Redirect After Action | redirect() function | references/server-actions-patterns.md |
See: references/server-actions-patterns.md for error handling, optimistic updates, file uploads, and advanced patterns.
Route Handlers are the App Router equivalent of API Routes.
// app/api/posts/route.ts
export async function GET(request: Request) {
const posts = await db.posts.findMany()
return Response.json({ posts })
}
export async function POST(request: Request) {
const body = await request.json()
const post = await db.posts.create({ data: body })
return Response.json({ post }, { status: 201 })
}
Dynamic Routes (with async params):
// app/api/posts/[id]/route.ts
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params // Await in Next.js 16
const post = await db.posts.findUnique({ where: { id } })
return post ? Response.json({ post }) : Response.json({ error: 'Not found' }, { status: 404 })
}
See: templates/route-handler-api.ts for search params, webhooks, and streaming patterns.
| Feature | Usage |
|---|---|
| React Compiler | experimental: { reactCompiler: true } - Auto-memoization |
| View Transitions | useTransition() + router.push() |
| useEffectEvent | Stable event handlers without deps |
// Static metadata
export const metadata: Metadata = {
title: 'My Blog',
description: 'A blog about Next.js',
openGraph: { title: 'My Blog', images: ['/og-image.jpg'] },
}
// Dynamic metadata (await params in Next.js 16)
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
const post = await db.posts.findUnique({ where: { id } })
return { title: post.title, description: post.excerpt }
}
// next/image
import Image from 'next/image'
<Image src="/profile.jpg" alt="Profile" width={500} height={500} priority />
// next/font
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })
<html className={inter.variable}>
Remote images: Configure images.remotePatterns in next.config.ts.
params is a PromiseError: Type 'Promise<{ id: string }>' is not assignable to type '{ id: string }'
Solution: Await params in Next.js 16:
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
}
middleware.ts is deprecatedWarning: middleware.ts is deprecated. Use proxy.ts instead.
Solution: Rename file and function:
// Rename: middleware.ts → proxy.ts
// Rename function: middleware → proxy
export function proxy(request: NextRequest) {
// Same logic
}
default.jsError: Parallel route @modal was matched but no default.js was found
Solution: Add default.tsx:
// app/@modal/default.tsx
export default function ModalDefault() {
return null
}
Error: You're importing a component that needs useState. It only works in a Client Component
Solution: Add 'use client':
'use client'
import { useState } from 'react'
export function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>{count}</button>
}
fetch() not cachingCause: Next.js 16 uses opt-in caching with "use cache".
Solution: Add "use cache" directive:
'use cache'
export async function getPosts() {
const response = await fetch('/api/posts')
return response.json()
}
See All 18 Errors: references/error-catalog.md
| Pattern | Usage |
|---|---|
| Lazy Loading | const HeavyComp = dynamic(() => import('./Heavy'), { ssr: false }) |
| Code Splitting | Automatic per route - each page.tsx gets own bundle |
| Turbopack | Default in Next.js 16, opt out with --webpack flag |
| PPR | experimental: { ppr: true } + <Suspense> boundaries |
{
"compilerOptions": {
"strict": true,
"baseUrl": ".",
"paths": { "@/*": ["./*"] }
}
}
| Reference | Load When... |
|---|---|
next-16-migration-guide.md | Migrating from Next.js 15, async params errors, proxy.ts setup |
server-actions-patterns.md | Error handling, optimistic updates, file uploads, advanced forms |
caching-apis.md | ISR, tag-based revalidation, updateTag(), refresh(), PPR details |
error-catalog.md | Debugging any Next.js error, comprehensive error solutions |
top-errors.md | Quick fixes for the 5 most common Next.js errors |
| Type | Files |
|---|---|
| References | error-catalog.md, top-errors.md, next-16-migration-guide.md, server-actions-patterns.md, caching-apis.md |
| Templates | async-params-page.tsx, server-action-form.tsx, route-handler-api.ts, cache-component-use-cache.tsx, parallel-routes-with-default.tsx, proxy-migration.ts |
| Skill | Purpose |
|---|---|
cloudflare-nextjs | Deploy to Cloudflare Workers |
tailwind-v4-shadcn | Styling |
clerk-auth | Authentication |
drizzle-orm-d1 | Database |
react-hook-form-zod | Forms |
zustand-state-management | Client state |
Official Docs: https://nextjs.org/docs | App Router: https://nextjs.org/docs/app
Version: Next.js 16.0.0 | React 19.2.0 | Node.js 20.9+ | TypeScript 5.3+ Production Tested: E-commerce, SaaS, content sites | Token Savings: 65-70%
Expert guidance for Next.js Cache Components and Partial Prerendering (PPR). **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts/next.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations. **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions. **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()/revalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.