| name | hono-core |
| description | Hono ultrafast web framework fundamentals - routing, context, handlers, and response patterns for multi-runtime deployment |
| skill_version | 1.0.0 |
| updated_at | "2025-01-03T00:00:00.000Z" |
| tags | ["hono","web-framework","routing","typescript","cloudflare-workers","deno","bun","nodejs"] |
| progressive_disclosure | {"entry_point":{"summary":"Ultrafast web framework built on Web Standards for Cloudflare Workers, Deno, Bun, Node.js","when_to_use":"Building APIs/web apps that need multi-runtime deployment, edge computing, or lightweight performance","quick_start":"1. npm create hono@latest 2. Define routes with app.get/post 3. Return responses via context"},"references":[]} |
| context_limit | 800 |
Hono - Ultrafast Web Framework
Overview
Hono is a small, simple, and ultrafast web framework built on Web Standards. It runs on Cloudflare Workers, Deno, Bun, Node.js, and more with the same codebase. The name means "flame" in Japanese.
Key Features:
- Built on Web Standards (Request/Response/fetch)
- Multi-runtime: Cloudflare Workers, Deno, Bun, Node.js, Vercel, AWS Lambda
- Ultrafast routing with RegExpRouter
- First-class TypeScript support
- Lightweight (~14KB minified)
- Rich middleware ecosystem
Installation:
npm create hono@latest my-app
npm install hono
npm install @hono/node-server
When to Use This Skill
Use Hono when:
- Building APIs for edge/serverless environments (Cloudflare Workers, Vercel Edge)
- Need multi-runtime portability (same code on Bun, Deno, Node.js)
- Want TypeScript-first development with excellent type inference
- Building lightweight, high-performance APIs
- Need built-in middleware for common patterns (CORS, auth, compression)
Hono vs Other Frameworks:
- Hono: Multi-runtime, Web Standards, ultrafast, edge-optimized
- Express: Node.js only, larger ecosystem, slower
- Fastify: Node.js only, schema-based, good performance
- Elysia: Bun only, excellent performance, different API style
Core Concepts
Creating an Application
import { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello Hono!"));
export default app;
With TypeScript Generics (for bindings/variables):
type Bindings = {
DATABASE_URL: string;
API_KEY: string;
};
type Variables = {
user: { id: string; name: string };
};
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>();
The Context Object (c)
The context c provides access to request data and response methods:
app.get("/users/:id", async (c) => {
const id = c.req.param("id");
const query = c.req.query("sort");
const queries = c.req.queries("tags");
const header = c.req.header("Authorization");
const body = await c.req.json();
const form = await c.req.formData();
const db = c.env.DATABASE_URL;
const user = c.get("user");
return c.text("Plain text");
return c.json({ id, name: "User" });
return c.html("<h1>Hello</h1>");
return c.redirect("/login");
return c.notFound();
});
Response Methods
c.text("Hello", 200);
c.json({ message: "Success" }, 201);
c.json({ error: "Not found" }, 404);
c.html("<h1>Hello</h1>");
c.redirect("/login");
c.redirect("/login", 301);
c.header("X-Custom", "value");
c.header("Cache-Control", "max-age=3600");
c.streamText(async (stream) => {
await stream.write("Hello ");
await stream.write("World!");
});
return new Response("Raw", { status: 200 });
Routing Patterns
Basic Routing
const app = new Hono();
app.get("/users", getUsers);
app.post("/users", createUser);
app.put("/users/:id", updateUser);
app.delete("/users/:id", deleteUser);
app.patch("/users/:id", patchUser);
app.all("/webhook", handleWebhook);
app.on("PURGE", "/cache", purgeCache);
app.on(["GET", "POST"], "/form", handleForm);
Path Parameters
app.get("/users/:id", (c) => {
const id = c.req.param("id");
return c.json({ id });
});
app.get("/posts/:postId/comments/:commentId", (c) => {
const { postId, commentId } = c.req.param();
return c.json({ postId, commentId });
});
app.get("/api/animal/:type?", (c) => {
const type = c.req.param("type") || "all";
return c.json({ type });
});
app.get("/posts/:id{[0-9]+}", (c) => {
const id = c.req.param("id");
return c.json({ id });
});
app.get("/files/*", (c) => {
const path = c.req.param("*");
return c.text(`File: ${path}`);
});
Route Grouping
const api = new Hono();
api.get("/users", getUsers);
api.get("/posts", getPosts);
const app = new Hono();
app.route("/api/v1", api);
const v2 = new Hono().basePath("/api/v2");
v2.get("/users", getUsers);
app.get("/a", handlerA).post("/b", handlerB).delete("/c", handlerC);
Route Organization (Multi-File)
import { Hono } from "hono";
const users = new Hono();
users.get("/", async (c) => {
return c.json({ users: [] });
});
users.post("/", async (c) => {
const body = await c.req.json();
return c.json({ created: body }, 201);
});
users.get("/:id", async (c) => {
const id = c.req.param("id");
return c.json({ id });
});
export default users;
import { Hono } from "hono";
import users from "./routes/users";
import posts from "./routes/posts";
const app = new Hono();
app.route("/users", users);
app.route("/posts", posts);
export default app;
Handler Patterns
Inline Handlers
app.get("/hello", (c) => c.text("Hello!"));
app.get("/users", async (c) => {
const users = await fetchUsers();
return c.json({ users });
});
app.get("/admin", authenticate, authorize, (c) => {
return c.json({ admin: true });
});
Using Factory for Type-Safe Handlers
import { createFactory } from "hono/factory";
const factory = createFactory<{ Bindings: Bindings }>();
const getUser = factory.createHandlers(async (c) => {
const id = c.req.param("id");
const db = c.env.DATABASE_URL;
return c.json({ id });
});
app.get("/users/:id", ...getUser);
Error Handling
Built-in Error Handling
import { HTTPException } from "hono/http-exception";
app.get("/users/:id", async (c) => {
const user = await findUser(c.req.param("id"));
if (!user) {
throw new HTTPException(404, { message: "User not found" });
}
return c.json(user);
});
app.onError((err, c) => {
console.error(`${err}`);
if (err instanceof HTTPException) {
return err.getResponse();
}
return c.json({ error: "Internal Server Error" }, 500);
});
app.notFound((c) => {
return c.json({ error: "Route not found" }, 404);
});
Custom Error Classes
class ValidationError extends HTTPException {
constructor(errors: string[]) {
super(400, {
message: "Validation failed",
cause: errors,
});
}
}
class AuthenticationError extends HTTPException {
constructor() {
super(401, { message: "Authentication required" });
}
}
Runtime-Specific Exports
Cloudflare Workers
import { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello Cloudflare!"));
export default app;
Node.js
import { serve } from "@hono/node-server";
import { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello Node!"));
serve({
fetch: app.fetch,
port: 3000,
});
Bun
import { Hono } from "hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello Bun!"));
export default {
port: 3000,
fetch: app.fetch,
};
Deno
import { Hono } from "npm:hono";
const app = new Hono();
app.get("/", (c) => c.text("Hello Deno!"));
Deno.serve(app.fetch);
Best Practices
Write Handlers Inline (Not Controllers)
app.get("/users/:id", async (c) => {
const id = c.req.param("id");
return c.json({ id });
});
class UserController {
getUser(c: Context) {
const id = c.req.param("id");
return c.json({ id });
}
}
Use Modular Routes
export const users = new Hono().get("/", listUsers).post("/", createUser).get("/:id", getUser);
app.route("/users", users);
Type Everything
type Bindings = {
DATABASE_URL: string;
JWT_SECRET: string;
MY_KV: KVNamespace;
};
const app = new Hono<{ Bindings: Bindings }>();
app.get("/", (c) => {
const url = c.env.DATABASE_URL;
const kv = c.env.MY_KV;
});
Quick Reference
Common Context Methods
| Method | Description | Example |
|---|
c.req.param(name) | Get path parameter | c.req.param('id') |
c.req.query(name) | Get query parameter | c.req.query('page') |
c.req.header(name) | Get request header | c.req.header('Authorization') |
c.req.json() | Parse JSON body | await c.req.json() |
c.req.formData() | Parse form data | await c.req.formData() |
c.text(str, status) | Text response | c.text('OK', 200) |
c.json(obj, status) | JSON response | c.json({}, 201) |
c.html(str) | HTML response | c.html('<h1>Hi</h1>') |
c.redirect(url) | Redirect | c.redirect('/login') |
c.header(k, v) | Set response header | c.header('X-Custom', 'val') |
c.set(key, val) | Set context variable | c.set('user', user) |
c.get(key) | Get context variable | c.get('user') |
c.env | Environment bindings | c.env.API_KEY |
HTTP Methods
app.get(path, ...handlers);
app.post(path, ...handlers);
app.put(path, ...handlers);
app.delete(path, ...handlers);
app.patch(path, ...handlers);
app.options(path, ...handlers);
app.head(path, ...handlers);
app.all(path, ...handlers);
app.on(method, path, ...handlers);
Related Skills
- hono-middleware - Middleware patterns and composition
- hono-validation - Request validation with Zod
- hono-rpc - Type-safe RPC client
- hono-testing - Testing patterns
- hono-jsx - Server-side JSX rendering
- hono-cloudflare - Cloudflare Workers deployment
Version: Hono 4.x
Last Updated: January 2025
License: MIT