Hono Framework Reference
Hono — ultrafast edge-first web framework for TypeScript. Works on Cloudflare Workers, Deno, Bun, Node.js, and Vercel Edge.
1. Routing
import { Hono } from 'hono'
const app = new Hono()
// Basic routes
app.get('/', (c) => c.text('Hello Hono!'))
app.post('/articles', createArticle)
app.put('/articles/:id', updateArticle)
app.delete('/articles/:id', deleteArticle)
// Path parameters
app.get('/articles/:id', (c) => {
const id = c.req.param('id')
return c.json({ id })
})
// Multiple params
app.get('/users/:userId/posts/:postId', (c) => {
const { userId, postId } = c.req.param()
return c.json({ userId, postId })
})
// Wildcard
app.get('/static/*', serveStatic({ root: './public' }))
// All methods
app.all('/any', (c) => c.text(`Method: ${c.req.method}`))
export default app
2. Route Groups & Chaining
import { Hono } from 'hono'
import { jwt } from 'hono/jwt'
const app = new Hono()
// Route group
const api = new Hono().basePath('/api/v1')
api.use('*', jwt({ secret: Bun.env.JWT_SECRET! }))
api.get('/articles', listArticles)
api.post('/articles', createArticle)
// Sub-app mounting
app.route('/api/v1', api)
// Method chaining on same path
app
.get('/users', listUsers)
.post('/users', createUser)
export default app
3. Middleware
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { logger } from 'hono/logger'
import { prettyJSON } from 'hono/pretty-json'
import { secureHeaders } from 'hono/secure-headers'
import { rateLimiter } from 'hono-rate-limiter'
const app = new Hono()
// Built-in middleware
app.use('*', logger())
app.use('*', cors({
origin: ['https://app.example.com'],
allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
allowHeaders: ['Authorization', 'Content-Type'],
credentials: true,
}))
app.use('*', secureHeaders())
app.use('/api/v1/*', prettyJSON())
// Custom middleware
app.use('*', async (c, next) => {
const start = Date.now()
await next()
c.header('X-Response-Time', `${Date.now() - start}ms`)
})
// Middleware on specific routes
app.use('/admin/*', async (c, next) => {
const payload = c.get('jwtPayload')
if (payload?.role !== 'admin') return c.json({ error: 'Forbidden' }, 403)
await next()
})
4. Validation with Zod
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
const createArticleSchema = z.object({
title: z.string().min(5).max(300),
content: z.string().min(50),
status: z.enum(['draft', 'published']).default('draft'),
tags: z.array(z.string()).max(10).optional(),
})
app.post(
'/articles',
zValidator('json', createArticleSchema),
async (c) => {
const data = c.req.valid('json') // fully typed!
const article = await db.articles.create(data)
return c.json(article, 201)
}
)
// Query param validation
const searchSchema = z.object({
q: z.string().optional(),
page: z.coerce.number().min(1).default(1),
limit: z.coerce.number().min(1).max(100).default(20),
})
app.get('/search', zValidator('query', searchSchema), (c) => {
const { q, page, limit } = c.req.valid('query')
return c.json({ q, page, limit })
})
5. RPC / hc Client
// server — define typed routes
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
const articlesRoute = new Hono()
.get('/', (c) => c.json({ articles: [] }))
.post('/', zValidator('json', createSchema), async (c) => {
const body = c.req.valid('json')
return c.json({ id: '1', ...body }, 201)
})
.get('/:id', (c) => c.json({ id: c.req.param('id') }))
export type AppType = typeof articlesRoute
export default articlesRoute
// client — fully type-safe, no code gen needed
import { hc } from 'hono/client'
import type { AppType } from './server'
const client = hc<AppType>('http://localhost:3000')
const res = await client.articles.$get()
const articles = await res.json() // typed!
const created = await client.articles.$post({
json: { title: 'Hello', content: 'World...', status: 'draft' },
})
const article = await created.json() // typed!
6. Deployment Targets
| Platform | Entry Point | Notes |
|---|---|---|
| Cloudflare Workers | export default app | Default, fastest |
| Bun | export default { port, fetch: app.fetch } | Native Bun server |
| Deno | Deno.serve(app.fetch) | Deno Deploy |
| Node.js | serve(app) from @hono/node-server | Node compatibility |
| Vercel Edge | export const GET = handle(app) | Vercel Edge Runtime |
| AWS Lambda | handle() from hono/aws-lambda | Lambda@Edge |