| name | hono |
| description | Hono web framework patterns: Context-based API (not Express req/res), async middleware, Cloudflare/Bun/Node adapters, typed routes. Use when working with Hono projects. |
| proactive | match |
| match | ["hono","from 'hono'","c.json","c.text","c.env"] |
Hono Web Framework Skill
Lightweight, multi-runtime web framework. Key patterns that differ from Express.
Quick Reference
Minimal App
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Hono!'))
export default app
Key Differences from Express
| Express | Hono |
|---|
req.params.id | c.req.param('id') |
res.json(data) | return c.json(data) |
next() callback | await next() async |
process.env | c.env (Workers) |
Context Object (NOT req/res)
app.get('/users/:id', (c) => {
const id = c.req.param('id')
const page = c.req.query('page')
const auth = c.req.header('Authorization')
const body = await c.req.json()
const form = await c.req.parseBody()
return c.json({ id, page })
})
Must return response:
app.get('/', (c) => { c.json({ ok: true }) })
app.get('/', (c) => { return c.json({ ok: true }) })
Async Middleware
app.use('*', (c, next) => { next() })
app.use('*', async (c, next) => {
console.log('before')
await next()
console.log('after')
})
Built-in Middleware
import { cors } from 'hono/cors'
import { logger } from 'hono/logger'
import { jwt } from 'hono/jwt'
import { validator } from 'hono/validator'
app.use('*', logger())
app.use('/api/*', cors())
app.post('/post', validator('json', (value, c) => {
if (!value.title) return c.text('Invalid', 400)
return value
}))
RPC Client (hc)
const route = app.get('/api', (c) => c.json({ ok: true }))
export type AppType = typeof route
import { hc } from 'hono/client'
const client = hc<AppType>('http://localhost:8787')
const res = await client.api.$get()
JSX Engine
import { Hono } from 'hono'
import { jsxRenderer } from 'hono/jsx-renderer'
const app = new Hono()
app.get('*', jsxRenderer(({ children }) => <html><body>{children}</body></html>))
app.get('/', (c) => c.render(<h1>Hello!</h1>))
Runtime Detection
import { getRuntimeKey } from 'hono/adapter'
const runtime = getRuntimeKey()
Cloudflare Workers
type Bindings = {
MY_KV: KVNamespace
API_KEY: string
}
const app = new Hono<{ Bindings: Bindings }>()
app.get('/', (c) => {
const key = c.env.API_KEY
return c.json({ key })
})
export default app
Node.js Setup
import { Hono } from 'hono'
import { serve } from '@hono/node-server'
const app = new Hono()
app.get('/', (c) => c.text('Hello Node!'))
serve({ fetch: app.fetch, port: 3000 })
v3 → v4 Migration
| v3 | v4 |
|---|
c.jsonT() | c.json() |
c.stream() | import { stream } from 'hono/streaming' |
hono/nextjs | hono/vercel |
Anti-patterns
export const env = (globalThis as any).env
import { env } from './env'
app.get('/', (c) => c.json({ key: c.env.API_KEY }))
Reference: Hono Docs, GitHub