Next.js App Router API patterns — Route Handlers, Server Actions, middleware, validation, caching, error handling
92
90%
Does it follow best practices?
Impact
95%
1.58xAverage score across 5 eval scenarios
Passed
No known issues
{
"instruction": "Explicitly control caching in GET Route Handlers and Server Component data fetching",
"relevant_when": "Agent writes GET Route Handlers or fetches data in Server Components",
"context": "Next.js App Router caches GET Route Handlers by default in production -- if the handler does not use dynamic APIs (cookies(), headers(), request properties), it is treated as static and cached indefinitely. This causes stale data bugs that only appear in production. Handlers serving dynamic data must either export 'dynamic = force-dynamic', use request-dependent APIs, or use fetch with cache/revalidate options. After mutations, revalidatePath or revalidateTag must be called to bust the cache.",
"sources": [
{
"type": "file",
"filename": "skills/nextjs-api-patterns/SKILL.md",
"tile": "tessl-labs/nextjs-api-patterns@0.2.0"
}
],
"checklist": [
{
"name": "get-handler-cache-control",
"rule": "GET Route Handlers that serve dynamic data either export 'dynamic = force-dynamic', use request-dependent APIs (cookies, headers, searchParams), or set explicit revalidation -- not left as implicitly cached",
"relevant_when": "Agent writes GET Route Handlers that return data from a database or external service"
},
{
"name": "fetch-cache-options",
"rule": "Server Component fetch calls include explicit cache control: { next: { revalidate: N } } for time-based, { next: { tags: [...] } } for on-demand, or { cache: 'no-store' } for always-fresh data",
"relevant_when": "Agent fetches data in Server Components"
},
{
"name": "mutation-revalidation",
"rule": "After data mutations (in Server Actions or Route Handlers), revalidatePath() or revalidateTag() is called to ensure the cache reflects the change",
"relevant_when": "Agent writes code that mutates data and needs the UI to reflect the change"
}
]
}