hono
Hono is a small, fast web framework built on Web Standards that runs across many JavaScript runtimes (Cloudflare Workers, Deno, Bun, AWS Lambda, Vercel, Node.js, and more). It uses the Fetch API’s Req
Hono
Hono is a small, fast web framework built on Web Standards that runs across many JavaScript runtimes (Cloudflare Workers, Deno, Bun, AWS Lambda, Vercel, Node.js, and more). It uses the Fetch API’s Request/Response model and provides a clean, TypeScript-first routing and middleware system with helpful built‑in utilities (cookies, validation, JSX rendering, streaming, and adapters).
Quick References
| File | Purpose |
|---|---|
src/index.ts | Main package entry point exports (Hono and public types) |
src/hono-base.ts | Core app API (routing, middleware, fetch/request entrypoints) |
src/context.ts | Context API (response helpers, headers, env, renderer) |
src/types.ts | Public TypeScript types (Env, Handler, Schema, TypedResponse, etc.) |
README.md | High-level overview and quick start example |
When to Use
- Build APIs or web apps that must run on multiple runtimes with the same codebase.
- You want a lightweight router with middleware support and Web‑standard Request/Response handling.
- You need strong TypeScript inference for routes, validators, and client calls.
Installation
npm install hono
Core Usage
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hono!'))
app.get('/users/:id', (c) => c.json({ id: c.req.param('id') }))
export default app
Key app entrypoints from HonoBase (src/hono-base.ts):
app.get/post/put/delete/patch/options/all(...): register routesapp.use(...): register middlewareapp.on(method, path, ...): register custom method routesapp.route('/base', subApp): mount another Hono instanceapp.basePath('/api'): apply a base path to a new app instanceapp.onError(handler): custom error handlingapp.notFound(handler): custom 404 handlerapp.fetch(request, env?, executionCtx?): standard Fetch entrypointapp.request(urlOrRequest, init?, env?, executionCtx?): convenience helper for tests and local calls
Context & Request Helpers
From src/context.ts and src/request.ts:
c.req.param('id')/c.req.param()for path paramsc.req.query('q')/c.req.query()for query paramsc.req.queries('tags')for multi-value query paramsc.req.header('Header-Name')for request headersc.req.json(),c.req.text(),c.req.formData()for body parsing (cached)c.req.valid('json' | 'form' | 'query' | 'param' | 'header' | 'cookie')after validationc.text(),c.json(),c.html(),c.body(),c.redirect()to return responsesc.header(name, value)to set headersc.status(code)to set statusc.set()/c.get()/c.varfor per-request variables
Configuration & Presets
Hono accepts options (src/hono-base.ts):
import { Hono } from 'hono'
import { RegExpRouter } from 'hono/router/reg-exp-router'
const app = new Hono({
strict: true,
router: new RegExpRouter(),
getPath: (req) => new URL(req.url).pathname,
})
Presets (router-focused builds):
hono/tiny→PatternRouter(src/preset/tiny.ts)hono/quick→SmartRouterwithLinearRouter+TrieRouter(src/preset/quick.ts)
import { Hono } from 'hono/tiny'
// or
import { Hono } from 'hono/quick'
Middleware & Helpers (Subpath Imports)
Hono exposes many built‑in middleware and helpers via subpath exports (see package.json and src/middleware/**, src/helper/**):
import { cors } from 'hono/cors'
import { logger } from 'hono/logger'
import { basicAuth } from 'hono/basic-auth'
import { jwt } from 'hono/jwt'
import { serveStatic } from 'hono/bun' // runtime-specific
import { getCookie, setCookie } from 'hono/cookie'
import { matchedRoutes } from 'hono/route'
import { html, raw } from 'hono/html'
Notable built‑ins:
- Auth:
basicAuth,bearerAuth,jwt,jwk - HTTP:
cors,csrf,etag,timeout,prettyJson,requestId,secureHeaders,methodOverride - Content:
bodyLimit,compress,serveStatic,jsxRenderer - Utilities:
cookie,route,accepts,streaming,ssg,adapter,factory,proxy,ws,conninfo
Runtime Adapters
Adapters provide runtime-specific entrypoints:
- Cloudflare Workers: export default app (Fetch handler)
- Cloudflare Pages:
handle(app)fromhono/cloudflare-pages - AWS Lambda:
handle(app)fromhono/aws-lambda - Vercel:
handle(app)fromhono/vercel - Service Worker:
fire(app)fromhono/service-worker
Examples:
// AWS Lambda
import { Hono } from 'hono'
import { handle } from 'hono/aws-lambda'
const app = new Hono()
app.get('/', (c) => c.text('Hello from Lambda'))
export const handler = handle(app)
// Cloudflare Pages
import { Hono } from 'hono'
import { handle } from 'hono/cloudflare-pages'
const app = new Hono()
app.get('/', (c) => c.text('Hello Pages'))
export const onRequest = handle(app)
JSX Rendering
Hono ships a JSX runtime and a renderer middleware:
import { Hono } from 'hono'
import { jsxRenderer } from 'hono/jsx-renderer'
const app = new Hono()
app.get('/page/*', jsxRenderer(({ children }) => (
<html>
<body>
<header>Menu</header>
<main>{children}</main>
</body>
</html>
)))
app.get('/page/about', (c) => c.render(<h1>About</h1>))
JSX runtime exports are available at hono/jsx, and streaming helpers at hono/jsx/streaming.
Client (Typed HTTP Calls)
hono/client exposes hc to build a typed client:
import { hc } from 'hono/client'
import type { AppType } from './app' // exported type from your Hono app
const client = hc<AppType>('https://api.example.com')
const res = await client.users.$get({ query: { limit: '10' } })
const data = await res.json()
Best Practices
- Use
c.req.json(),c.req.text(), orc.req.parseBody()instead of consumingc.req.rawdirectly; Hono caches parsed bodies and enables cloning viacloneRawRequest. - Always return a
Responseorawait next()in middleware—Hono will throw if the context is not finalized. - Prefer subpath imports (e.g.,
hono/cors,hono/logger) so you only bundle the middleware you use.
Common Patterns
Basic routing + middleware:
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { cors } from 'hono/cors'
const app = new Hono()
app.use('*', logger())
app.use('/api/*', cors())
app.get('/users/:id', (c) => {
const id = c.req.param('id')
const fields = c.req.query('fields')
return c.json({ id, fields })
})
app.post('/users', async (c) => {
const body = await c.req.json()
return c.json({ ok: true, body }, 201)
})
export default app
Validation with validator() and c.req.valid():
import { Hono } from 'hono'
import { validator } from 'hono/validator'
import { HTTPException } from 'hono/http-exception'
const app = new Hono()
app.post(
'/login',
validator('json', (value) => {
if (!value || typeof value !== 'object' || typeof value.email !== 'string') {
throw new HTTPException(400, { message: 'Invalid payload' })
}
return { email: value.email }
}),
(c) => {
const { email } = c.req.valid('json')
return c.json({ email })
}
)
API Quick Reference
| Export | Type | Description |
|---|---|---|
Hono | class | Main application class with routing, middleware, and fetch() entrypoint |
Context | class | Per-request context (c.req, response helpers, env, headers) |
HonoRequest | class | Request helpers (param, query, body parsers, valid) |
HTTPException | class | Throw HTTP errors with status and optional Response |
validator | function | Validation middleware factory for json/form/query/param/header/cookie |
hc | function | Typed HTTP client generator for Hono route types |
cors | middleware | CORS handling (hono/cors) |
basicAuth | middleware | HTTP Basic Auth (hono/basic-auth) |
jwt | middleware | JWT verification and helpers (hono/jwt) |
jsxRenderer | middleware | JSX rendering pipeline (hono/jsx-renderer) |
Key Types
Commonly imported from hono (src/types.ts, src/context.ts):
Env(withBindingsandVariables)Handler,MiddlewareHandler,NextSchema,Input,TypedResponse,ValidationTargetsContext,HonoRequestInferRequestType,InferResponseType,ClientRequestOptions(fromhono/client)
This combination of Web‑standard APIs, runtime adapters, and a rich middleware/helper ecosystem makes Hono a good fit for production APIs and edge‑native applications.