Last Updated: 3/11/2026
Best Practices
Hono is flexible, but following these best practices will help you build better applications.
Avoid Controllers
Don’t create Ruby on Rails-like controllers:
// ❌ Avoid
const booksList = (c: Context) => {
return c.json('list books')
}
app.get('/books', booksList)The issue: Path parameters can’t be inferred without complex generics.
// ❌ Avoid
const bookPermalink = (c: Context) => {
const id = c.req.param('id') // Can't infer type
return c.json(`get ${id}`)
}Instead, write handlers inline:
// ✅ Recommended
app.get('/books/:id', (c) => {
const id = c.req.param('id') // Type is inferred!
return c.json(`get ${id}`)
})Use Factory for Reusable Handlers
If you need reusable handlers, use factory.createHandlers():
import { createFactory } from 'hono/factory'
import { logger } from 'hono/logger'
const factory = createFactory()
const middleware = factory.createMiddleware(async (c, next) => {
c.set('foo', 'bar')
await next()
})
const handlers = factory.createHandlers(logger(), middleware, (c) => {
return c.json(c.var.foo)
})
app.get('/api', ...handlers)Building Larger Applications
Use app.route() to organize your code:
authors.ts:
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.json('list authors'))
app.post('/', (c) => c.json('create author', 201))
app.get('/:id', (c) => c.json(`get ${c.req.param('id')}`))
export default appbooks.ts:
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.json('list books'))
app.post('/', (c) => c.json('create book', 201))
app.get('/:id', (c) => c.json(`get ${c.req.param('id')}`))
export default appindex.ts:
import { Hono } from 'hono'
import authors from './authors'
import books from './books'
const app = new Hono()
app.route('/authors', authors)
app.route('/books', books)
export default appWith RPC
For type-safe RPC, chain your routes:
authors.ts:
import { Hono } from 'hono'
const app = new Hono()
.get('/', (c) => c.json('list authors'))
.post('/', (c) => c.json('create author', 201))
.get('/:id', (c) => c.json(`get ${c.req.param('id')}`))
export default app
export type AppType = typeof appClient:
import type { AppType } from './authors'
import { hc } from 'hono/client'
const client = hc<AppType>('http://localhost')
// Fully typed!See RPC with larger applications for details.