CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/hono-best-practices

Production Hono patterns — zValidator hooks, typed generics, error handling, middleware composition, testing, and multi-runtime deployment

87

2.57x
Quality

80%

Does it follow best practices?

Impact

98%

2.57x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-3/

{
  "context": "Tests whether the agent proactively applies Hono best practices when building a standard CRUD API that does not mention error handling patterns, validation hooks, middleware composition, or typed generics in the requirements. The task only asks for endpoints and business rules.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "zValidator with hook callback",
      "description": "zValidator from @hono/zod-validator is used for request body validation AND includes a hook callback (third argument) that returns c.json() with a structured error object on validation failure -- not the default plain-text 400 response",
      "max_score": 15
    },
    {
      "name": "c.req.valid() not c.req.json()",
      "description": "After zValidator middleware, the route handler accesses the validated body via c.req.valid('json') -- not c.req.json() which re-parses and loses type safety",
      "max_score": 10
    },
    {
      "name": "Global onError handler",
      "description": "app.onError is registered with a handler that catches errors and returns structured JSON responses with { error: { code, message } } format, and does not leak stack traces for internal errors",
      "max_score": 12
    },
    {
      "name": "notFound handler",
      "description": "app.notFound is registered to return a JSON 404 response instead of Hono's default plain-text 404",
      "max_score": 8
    },
    {
      "name": "Env generic with Variables",
      "description": "The Hono app is created with a typed Env generic: new Hono<{ Variables: {...} }>() or equivalent type alias -- not bare new Hono()",
      "max_score": 10
    },
    {
      "name": "Middleware with await next()",
      "description": "Any custom middleware correctly uses 'await next()' -- not bare next() without await",
      "max_score": 8
    },
    {
      "name": "Built-in middleware registered",
      "description": "At least logger() and secureHeaders() from hono built-in middleware are registered on the app",
      "max_score": 8
    },
    {
      "name": "Route grouping with app.route()",
      "description": "Routes are organized using separate Hono instances mounted via app.route('/prefix', child) -- not all routes defined directly on the main app",
      "max_score": 7
    },
    {
      "name": "Node.js entry point with @hono/node-server",
      "description": "The server entry point uses serve() from @hono/node-server (not export default app) and @hono/node-server is listed in package.json dependencies",
      "max_score": 10
    },
    {
      "name": "App separated from entry point",
      "description": "The Hono app is defined in a separate file (e.g. app.ts) from the server entry point (e.g. server.ts) so it can be imported for testing",
      "max_score": 6
    },
    {
      "name": "Consistent error response shape",
      "description": "All error responses (validation, not-found, conflicts, internal) use the same consistent shape: { error: { code, message } }",
      "max_score": 6
    }
  ]
}

evals

tile.json