CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/nextjs-api-patterns

Next.js App Router API patterns — Route Handlers, Server Actions, middleware, validation, caching, error handling

92

1.58x
Quality

90%

Does it follow best practices?

Impact

95%

1.58x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-5/

{
  "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
    }
  ]
}

evals

tile.json