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
{
"context": "Tests a combination of patterns: middleware with matcher for auth, dynamic route params awaiting, pagination via searchParams, caching control for dynamic dashboard data, structured error responses, and validation on the POST endpoint. The task mentions auth but does not mention middleware best practices, caching, or validation specifics.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Middleware with proper matcher",
"description": "middleware.ts exports a config.matcher that targets /api/dashboard and /dashboard routes while excluding _next/static, _next/image, and other static assets",
"max_score": 12
},
{
"name": "Auth check in middleware returns 401",
"description": "Middleware checks Authorization header for Bearer token on dashboard routes and returns NextResponse.json with 401 status and structured error body when missing or invalid",
"max_score": 10
},
{
"name": "Params awaited in dynamic routes",
"description": "The [id] route handler awaits params: 'const { id } = await params' with type { params: Promise<{ id: string }> } -- not accessing params.id directly",
"max_score": 13
},
{
"name": "Search params for pagination",
"description": "The orders list endpoint reads pagination parameters from request.nextUrl.searchParams (page, limit) with sensible defaults",
"max_score": 8
},
{
"name": "GET cache control for dynamic data",
"description": "GET handlers serving dashboard data opt out of static caching -- either via 'export const dynamic = force-dynamic', reading headers/cookies (which the auth check naturally does), or request.nextUrl usage",
"max_score": 12
},
{
"name": "Validation on POST endpoint",
"description": "The POST /api/dashboard/orders/[id]/notes endpoint validates the note body with zod or equivalent, returning 400 with field-level errors for invalid input",
"max_score": 10
},
{
"name": "request.json() wrapped in try/catch",
"description": "The POST handler wraps request.json() in try/catch for malformed JSON",
"max_score": 8
},
{
"name": "Structured error responses",
"description": "All error responses use a consistent { error: { code, message } } shape with semantic status codes (400, 401, 404, 500)",
"max_score": 10
},
{
"name": "No internal error leaks",
"description": "Unexpected errors return a generic message -- no stack traces or internal details",
"max_score": 7
},
{
"name": "Functional implementation",
"description": "Dashboard stats, order listing with pagination, single order lookup, and note creation all work correctly with seed data present",
"max_score": 10
}
]
}