Skills

Install

$ npx ai-agents-skills add --skill hono
Framework v1.1

Hono

Lightweight, type-safe APIs for edge/serverless platforms.

When to Use

  • Edge/serverless APIs
  • Lightweight routing/middleware
  • Edge platforms (Cloudflare Workers, Deno Deploy, Bun)

Don’t use for:

  • Full-stack SSR + React (use Next.js)
  • Heavy ORM/session state (use Express/NestJS)
  • Long-running processes (use Node.js server)

Critical Patterns

✅ REQUIRED: Route Chaining

Method chaining for compact route groups.

// CORRECT: chained routes on a single app instance
const app = new Hono()
  .get("/users", (c) => c.json(users))
  .post("/users", (c) => c.json(created, 201))
  .get("/users/:id", (c) => c.json(user));
// WRONG: separate app declarations or loose functions

✅ REQUIRED: Middleware Composition

app.use() for cross-cutting concerns; scope to paths.

// CORRECT: scoped middleware
app.use("*", logger());
app.use("*", cors());
app.use("/api/*", bearerAuth({ token: SECRET }));
// WRONG: auth middleware applied globally to public routes

✅ REQUIRED: Zod Validation with zValidator

@hono/zod-validator for body/param/query validation.

import { zValidator } from "@hono/zod-validator";
import { z } from "zod";
const CreateUser = z.object({ name: z.string(), email: z.string().email() });
app.post("/users", zValidator("json", CreateUser), (c) => {
  const data = c.req.valid("json"); // fully typed
  return c.json({ id: 1, ...data }, 201);
});

✅ REQUIRED: Context Helpers

Use c.json(), c.text(), c.html() over manual Response.

// CORRECT: context helpers set headers automatically
app.get("/health", (c) => c.text("ok"));
app.get("/data", (c) => c.json({ status: "up" }));
app.get("/old", (c) => c.redirect("/new", 301));
// WRONG: new Response(JSON.stringify({ status: "up" }))

✅ REQUIRED: Environment Bindings (Cloudflare Workers)

Access bindings via generic type parameter.

type Env = { Bindings: { DB: D1Database; KV: KVNamespace } };
const app = new Hono<Env>();
app.get("/items", async (c) => {
  const result = await c.env.DB.prepare("SELECT * FROM items").all();
  return c.json(result);
});

Decision Tree

Cloudflare Workers?
  → Use Hono<{ Bindings: ... }> for typed env

Need validation?
  → Use @hono/zod-validator middleware

Sub-routes?
  → Use app.route("/prefix", subApp)

Auth required?
  → Scope bearerAuth or custom middleware to protected paths

Returning JSON?
  → Always use c.json() with explicit status codes

Streaming response?
  → Use c.stream() or c.streamText()

Multiple platforms?
  → Use adapter exports (hono/cloudflare-workers, hono/bun)

Example

import { Hono } from "hono";
import { logger } from "hono/logger";
import { zValidator } from "@hono/zod-validator";
import { z } from "zod";
const app = new Hono();
app.use("*", logger());
const ItemSchema = z.object({ name: z.string(), price: z.number().positive() });
app.get("/items", (c) => c.json(items));
app.post("/items", zValidator("json", ItemSchema), (c) => {
  const data = c.req.valid("json");
  return c.json({ id: crypto.randomUUID(), ...data }, 201);
});
export default app;

Edge Cases

  • Cold start: Hono ~14KB but bundled deps inflate; tree-shake aggressively.
  • Platform limits: CF Workers 128MB, 10ms CPU (free)/30s (paid); Deno Deploy 50ms CPU.
  • Streaming: Use c.stream() for chunked; not all platforms support full streaming.
  • Body parsing: Lazy JSON via c.req.json(); multipart needs hono/multipart.
  • Path params: All c.req.param() are strings; parse to numbers before DB.
  • CORS: Register cors() before handlers for OPTIONS.

Checklist

  • Routes use method chaining or app.route() for sub-apps
  • Middleware is scoped to relevant paths, not applied globally when unnecessary
  • Request bodies are validated with zValidator and Zod schemas
  • Responses use context helpers (c.json, c.text) with explicit status codes
  • Environment bindings are typed via the Hono generic parameter
  • CORS middleware is registered before route definitions
  • The final export matches the target platform adapter

Resources