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 middleware configuration (matcher, edge runtime compatibility, project root placement), Route Handler patterns for webhooks (JSON parsing safety, signature verification, structured responses), and caching control for the events listing endpoint. The task naturally requires middleware but does not specify best practices around matcher config or static asset exclusion.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Middleware with matcher config",
"description": "middleware.ts exports a config object with a matcher that targets the webhook routes and excludes _next/static, _next/image, and other static assets -- not running on every request",
"max_score": 14
},
{
"name": "Middleware at project root",
"description": "middleware.ts is placed at the project root alongside the app/ directory, not inside app/ or any subdirectory",
"max_score": 8
},
{
"name": "Middleware uses only Web APIs",
"description": "Middleware code uses only Edge Runtime compatible APIs (fetch, Request, Response, Headers, URL, NextResponse, NextRequest) -- no Node.js-only imports like fs, path, or crypto from node:crypto",
"max_score": 8
},
{
"name": "request.json() wrapped in try/catch",
"description": "The POST webhook handler wraps request.json() in try/catch to handle malformed JSON payloads, returning a 400 error with a structured response",
"max_score": 12
},
{
"name": "Webhook payload validation",
"description": "The webhook payload is validated (event type, required data fields) using a schema library or thorough checks before processing",
"max_score": 12
},
{
"name": "Structured error responses",
"description": "All error responses use a consistent shape like { error: { code, message } } with appropriate status codes -- 400 for bad payload, 401 for missing signature, 422 for unknown event type",
"max_score": 10
},
{
"name": "Signature verification",
"description": "The handler checks for the x-webhook-signature header and returns 401 if missing, before processing the payload",
"max_score": 10
},
{
"name": "GET events endpoint with cache control",
"description": "The GET /api/webhooks/payments/events endpoint explicitly opts out of caching (dynamic = 'force-dynamic' or uses request-dependent APIs) since event data changes with every webhook",
"max_score": 10
},
{
"name": "No internal error leaks",
"description": "Unexpected errors return a generic message with 500 status -- no stack traces or internal details leaked to the webhook provider",
"max_score": 8
},
{
"name": "Functional implementation",
"description": "Webhooks can be received and stored, events can be listed. The three event types are handled distinctly.",
"max_score": 8
}
]
}