Skip to main content
nextjs-dev Next.js 16 development patterns from Vercel's official Next.js Agent Skills (394 snippets). App Router, RSC boundaries, cache components, Turbopack, proxy.ts, Server Actions, metadata/SEO.
Ir para a instalação Skills Marketplace Descubra e explore skills de IA criadas pela comunidade.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Copiar promptMostrar detalhes do prompt Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
npx skills add https://github.com/ktg-one/goodai-mate --skill nextjs-devO comando permanece em uma só linha. Role horizontalmente para revisá-lo antes de copiar.
Prefere uma cópia local? Baixe os arquivos disponíveis atualmente no SkillsMP.
Baixar Zip Baixando... Mais deste repositório Good'ai brutalist/direct-mail frontend: brand tokens, stamp UI, voice hero, asset registry, and ESLint gates. Use when building or reviewing UI in goodai-mate, fixing design fidelity, prepping demos (ABS), running lint, or when the user says /goodai-frontend, goodai frontend, brutalist mail board, stamp design, or frontend-design for this project.
API Route Handler, Server Action, and data mutation patterns for Next.js 16. Zod validation, error handling, auth patterns, cache revalidation.
React 19 + Server Component patterns from official Vercel/React docs. Component templates, hooks patterns, RSC boundaries, performance optimization.
Ocupações relacionadas SOC
Baseado na classificação ocupacional SOC
name nextjs-dev description Next.js 16 development patterns from Vercel's official Next.js Agent Skills (394 snippets). App Router, RSC boundaries, cache components, Turbopack, proxy.ts, Server Actions, metadata/SEO. user-invocable false
Next.js 16 Development Patterns (Official Vercel Source)
Based on /vercel-labs/next-skills — the official Vercel-maintained skill pack for Next.js agents.
File Conventions (App Router)
File Purpose Scope page.tsxUI unique to a route Route segment layout.tsxShared UI wrapping children Route segment + children loading.tsxInstant loading UI (Suspense) Route segment error.tsxError boundary ('use client' required) Route segment not-found.tsx404 UI Route segment route.tsAPI route handler Route segment template.tsxRe-rendered layout (no state persistence) Route segment default.tsxParallel route fallback
global-error.tsxRoot error boundary App-wide
proxy.tsRequest rewriting/routing (replaces middleware in v16) Project root
Route Groups src/app/
(marketing)/ # force-static — landing, blog, docs
(app)/ # force-dynamic — dashboard, settings
(auth)/ # auth flows — login, register, callback
React Server Component (RSC) Boundaries
Decision Tree
Does it handle user interaction (clicks, forms, state)? → 'use client'
Does it only render data? → Server Component (default)
Does it need browser APIs (window, localStorage)? → 'use client'
Is it heavy (chart, editor, map)? → next/dynamic with ssr: false
Does it fetch data? → Server Component with async + direct DB/API call
Directives
'use server'
'use client'
'use cache'
Boundary Rules
Server Components can import Client Components ✅
Client Components CANNOT import Server Components ❌
Client Components CAN render Server Components as children ✅
'use client' marks the boundary — everything imported below is client
import ClientShell from './client-shell'
import ServerData from './server-data'
export default function Page ( ) {
return (
<ClientShell >
<ServerData /> {/* stays on server */}
</ClientShell >
)
}
Async Patterns (Next.js 16)
params and searchParams are Promises
export default async function Page ({
params,
}: {
params: Promise <{ slug: string }>
} ) {
const { slug } = await params
return <Article slug ={slug} />
}
export async function generateMetadata ({
params,
}: {
params: Promise <{ slug: string }>
} ) {
const { slug } = await params
return { title : `Article: ${slug} ` }
}
Parallel Data Fetching — ALWAYS for independent data
const [user, posts, comments] = await Promise .all ([
getUser (id),
getPosts (id),
getComments (id),
])
const user = await getUser (id)
const posts = await getPosts (id)
const comments = await getComments (id)
Suspense Streaming import { Suspense } from 'react'
export default function Dashboard ( ) {
return (
<div >
<h1 > Dashboard</h1 >
<Suspense fallback ={ <CardSkeleton /> }>
<RevenueChart /> {/* streams when ready */}
</Suspense >
<Suspense fallback ={ <TableSkeleton /> }>
<LatestInvoices /> {/* streams independently */}
</Suspense >
</div >
)
}
Cache Components (Next.js 16 PPR)
async function CachedProductList ( ) {
'use cache'
const products = await db.product .findMany ()
return <ProductGrid products ={products} />
}
import { cacheLife } from 'next/cache'
async function CachedStats ( ) {
'use cache'
cacheLife ('hours' )
const stats = await getStats ()
return <StatsDisplay stats ={stats} />
}
import { cacheTag } from 'next/cache'
async function CachedList ({ tag }: { tag: string } ) {
'use cache'
cacheTag (tag)
const items = await getItems ()
return <ItemList items ={items} />
}
Server Actions 'use server'
import { z } from 'zod'
import { revalidatePath, revalidateTag } from 'next/cache'
import { redirect } from 'next/navigation'
const CreateSchema = z.object ({
name : z.string ().min (1 ).max (100 ),
email : z.string ().email (),
})
export async function createUser (formData : FormData ) {
const parsed = CreateSchema .safeParse (Object .fromEntries (formData))
if (!parsed.success ) {
return { error : parsed.error .flatten () }
}
const session = await auth ()
if (!session) {
return { error : 'Unauthorized' }
}
const user = await db.user .create ({ data : parsed.data })
revalidatePath ('/users' )
redirect (`/users/${user.id} ` )
}
'use client'
import { useRouter } from 'next/navigation'
function UpdateButton ( ) {
const router = useRouter ()
async function handleUpdate ( ) {
await updateItem (id)
router.refresh ()
}
return <button onClick ={handleUpdate} > Update</button >
}
Data Fetching Patterns
async function ProductPage ({ params }: { params: Promise <{ id: string }> } ) {
const { id } = await params
const product = await getProduct (id)
return <ProductView product ={product} />
}
export const revalidate = 3600
async function BlogPage ( ) {
const posts = await getPosts ()
return <PostList posts ={posts} />
}
export async function generateStaticParams ( ) {
const posts = await getPosts ()
return posts.map ((post ) => ({ slug : post.slug }))
}
export const dynamic = 'force-dynamic'
Route Handlers
import { NextRequest , NextResponse } from 'next/server'
import { z } from 'zod'
const Schema = z.object ({
name : z.string ().min (1 ).max (100 ),
})
export async function POST (request : NextRequest ) {
try {
const body = await request.json ()
const parsed = Schema .safeParse (body)
if (!parsed.success ) {
return NextResponse .json (
{ error : 'Validation failed' , details : parsed.error .flatten () },
{ status : 400 }
)
}
const result = await createResource (parsed.data )
return NextResponse .json (result, { status : 201 })
} catch (error) {
console .error ('[API] POST /api/resource:' , error)
return NextResponse .json ({ error : 'Internal server error' }, { status : 500 })
}
}
proxy.ts (Replaces middleware.ts in Next.js 16)
import type { NextRequest } from 'next/server'
export function proxy (request : NextRequest ) {
const { pathname } = request.nextUrl
if (pathname.startsWith ('/blog' )) {
return { rewrite : new URL ('/marketing/blog' + pathname.slice (5 ), request.url ) }
}
if (pathname.startsWith ('/dashboard' ) && !request.cookies .get ('session' )) {
return { redirect : new URL ('/login' , request.url ) }
}
}
Metadata / SEO
export const metadata = {
title : 'My App' ,
description : 'App description' ,
openGraph : {
title : 'My App' ,
description : 'App description' ,
images : ['/og.png' ],
},
}
export async function generateMetadata ({ params }: { params: Promise <{ slug: string }> } ) {
const { slug } = await params
const post = await getPost (slug)
return {
title : post.title ,
description : post.excerpt ,
openGraph : { images : [post.coverImage ] },
}
}
import { ImageResponse } from 'next/og'
export async function GET (request : NextRequest ) {
const { searchParams } = new URL (request.url )
const title = searchParams.get ('title' ) ?? 'Default Title'
return new ImageResponse (
<div style ={{ fontSize: 48 , background: 'white ', width: '100 %', height: '100 %', display: 'flex ', alignItems: 'center ', justifyContent: 'center ' }}>
{title}
</div > ,
{ width : 1200 , height : 630 }
)
}
Parallel & Intercepting Routes
export default function Layout ({
children,
analytics,
team,
}: {
children: React.ReactNode
analytics: React.ReactNode
team: React.ReactNode
} ) {
return (
<div >
{children}
{analytics}
{team}
</div >
)
}
Import Rules (Critical for Bundle Size)
import { Button , Card , Input } from '@/components/ui'
import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import HeavyChart from '@/components/heavy-chart'
import dynamic from 'next/dynamic'
const HeavyChart = dynamic (() => import ('@/components/heavy-chart' ), {
ssr : false ,
loading : () => <ChartSkeleton /> ,
})
Turbopack (Default in Next.js 16)
Turbopack is the default bundler for both next dev and next build
No webpack configuration needed for standard use cases
Built-in CSS, PostCSS, and Tailwind CSS support
Filesystem caching enabled by default
const config = {
experimental : {
turbo : {
},
},
}
Environment Variables
NEXT_PUBLIC_* — exposed to client bundle (public values only)
Everything else — server-only (API keys, secrets, DB URLs)
Never import process.env in client components without NEXT_PUBLIC_ prefix
Use src/types/env.d.ts for typed environment variables
Error Handling
'use client'
export default function Error ({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
} ) {
return (
<div >
<h2 > Something went wrong</h2 >
<p > {error.message}</p >
<button onClick ={reset} > Try again</button >
</div >
)
}
'use client'
export default function GlobalError ({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
} ) {
return (
<html >
<body >
<h2 > Something went wrong</h2 >
<button onClick ={reset} > Try again</button >
</body >
</html >
)
}