Bun Hono Integration
Hono is a fast, lightweight web framework optimized for Bun.
Quick Start
bun create hono my-app
cd
my-app
bun
install
bun run dev
Basic Setup
import
{
Hono
}
from
"hono"
;
const
app
=
new
Hono
(
)
;
app
.
get
(
"/"
,
(
c
)
=>
c
.
text
(
"Hello Hono!"
)
)
;
app
.
get
(
"/json"
,
(
c
)
=>
c
.
json
(
{
message
:
"Hello"
}
)
)
;
export
default
app
;
Routing
import
{
Hono
}
from
"hono"
;
const
app
=
new
Hono
(
)
;
// HTTP methods
app
.
get
(
"/users"
,
(
c
)
=>
c
.
json
(
[
]
)
)
;
app
.
post
(
"/users"
,
(
c
)
=>
c
.
json
(
{
created
:
true
}
)
)
;
app
.
put
(
"/users/:id"
,
(
c
)
=>
c
.
json
(
{
updated
:
true
}
)
)
;
app
.
delete
(
"/users/:id"
,
(
c
)
=>
c
.
json
(
{
deleted
:
true
}
)
)
;
// All methods
app
.
all
(
"/any"
,
(
c
)
=>
c
.
text
(
"Any method"
)
)
;
// Path parameters
app
.
get
(
"/users/:id"
,
(
c
)
=>
{
const
id
=
c
.
req
.
param
(
"id"
)
;
return
c
.
json
(
{
id
}
)
;
}
)
;
// Multiple parameters
app
.
get
(
"/posts/:postId/comments/:commentId"
,
(
c
)
=>
{
const
{
postId
,
commentId
}
=
c
.
req
.
param
(
)
;
return
c
.
json
(
{
postId
,
commentId
}
)
;
}
)
;
// Wildcards
app
.
get
(
"/files/"
,
(
c
)
=>
{
const
path
=
c
.
req
.
path
;
return
c
.
text
(
File:
${
path
}
)
;
}
)
;
// Regex-like patterns
app
.
get
(
"/user/:id{[0-9]+}"
,
(
c
)
=>
c
.
json
(
{
id
:
c
.
req
.
param
(
"id"
)
}
)
)
;
export
default
app
;
Route Groups
import
{
Hono
}
from
"hono"
;
const
app
=
new
Hono
(
)
;
// Group routes
const
api
=
new
Hono
(
)
;
api
.
get
(
"/users"
,
(
c
)
=>
c
.
json
(
[
]
)
)
;
api
.
get
(
"/posts"
,
(
c
)
=>
c
.
json
(
[
]
)
)
;
app
.
route
(
"/api/v1"
,
api
)
;
// Basepath
const
app2
=
new
Hono
(
)
.
basePath
(
"/api/v2"
)
;
app2
.
get
(
"/users"
,
(
c
)
=>
c
.
json
(
[
]
)
)
;
// /api/v2/users
export
default
app
;
Request Handling
app
.
post
(
"/submit"
,
async
(
c
)
=>
{
// URL and method
console
.
log
(
c
.
req
.
url
)
;
console
.
log
(
c
.
req
.
method
)
;
// Headers
const
auth
=
c
.
req
.
header
(
"Authorization"
)
;
// Query params
const
page
=
c
.
req
.
query
(
"page"
)
;
const
{
limit
,
offset
}
=
c
.
req
.
query
(
)
;
// Body parsing
const
json
=
await
c
.
req
.
json
(
)
;
const
text
=
await
c
.
req
.
text
(
)
;
const
form
=
await
c
.
req
.
formData
(
)
;
const
arrayBuffer
=
await
c
.
req
.
arrayBuffer
(
)
;
// Parsed body (with validator)
const
body
=
c
.
req
.
valid
(
"json"
)
;
return
c
.
json
(
{
received
:
true
}
)
;
}
)
;
Response Types
app
.
get
(
"/responses"
,
(
c
)
=>
{
// Text
return
c
.
text
(
"Hello"
)
;
// JSON
return
c
.
json
(
{
data
:
"value"
}
)
;
// HTML
return
c
.
html
(
"Hello
"
)
;
// Redirect
return
c
.
redirect
(
"/other"
,
302
)
;
// Not Found
return
c
.
notFound
(
)
;
// Custom response
return
c
.
body
(
"Raw body"
,
200
,
{
"Content-Type"
:
"text/plain"
,
}
)
;
// Status
return
c
.
json
(
{
error
:
"Not found"
}
,
404
)
;
// Headers
c
.
header
(
"X-Custom"
,
"value"
)
;
return
c
.
json
(
{
ok
:
true
}
)
;
}
)
;
Middleware
import
{
Hono
}
from
"hono"
;
const
app
=
new
Hono
(
)
;
// Global middleware
app
.
use
(
""
,
async
(
c
,
next
)
=>
{
console
.
log
(
${
c
.
req
.
method
}
${
c
.
req
.
url
}
)
;
await
next
(
)
;
}
)
;
// Path-specific middleware
app
.
use
(
"/api/"
,
async
(
c
,
next
)
=>
{
const
auth
=
c
.
req
.
header
(
"Authorization"
)
;
if
(
!
auth
)
{
return
c
.
json
(
{
error
:
"Unauthorized"
}
,
401
)
;
}
await
next
(
)
;
}
)
;
// Multiple middleware
app
.
use
(
"/admin/"
,
authMiddleware
,
adminMiddleware
)
;
app
.
get
(
"/api/data"
,
(
c
)
=>
c
.
json
(
{
data
:
"protected"
}
)
)
;
export
default
app
;
Built-in Middleware
import
{
Hono
}
from
"hono"
;
import
{
cors
}
from
"hono/cors"
;
import
{
logger
}
from
"hono/logger"
;
import
{
basicAuth
}
from
"hono/basic-auth"
;
import
{
bearerAuth
}
from
"hono/bearer-auth"
;
import
{
compress
}
from
"hono/compress"
;
import
{
etag
}
from
"hono/etag"
;
import
{
secureHeaders
}
from
"hono/secure-headers"
;
const
app
=
new
Hono
(
)
;
// CORS
app
.
use
(
""
,
cors
(
)
)
;
app
.
use
(
"/api/"
,
cors
(
{
origin
:
"https://example.com"
,
allowMethods
:
[
"GET"
,
"POST"
]
,
}
)
)
;
// Logger
app
.
use
(
""
,
logger
(
)
)
;
// Basic Auth
app
.
use
(
"/admin/"
,
basicAuth
(
{
username
:
"admin"
,
password
:
"secret"
,
}
)
)
;
// Bearer Token
app
.
use
(
"/api/"
,
bearerAuth
(
{
token
:
"my-token"
,
}
)
)
;
// Compression
app
.
use
(
""
,
compress
(
)
)
;
// ETag
app
.
use
(
""
,
etag
(
)
)
;
// Security headers
app
.
use
(
""
,
secureHeaders
(
)
)
;
export
default
app
;
Validation with Zod
import
{
Hono
}
from
"hono"
;
import
{
zValidator
}
from
"@hono/zod-validator"
;
import
{
z
}
from
"zod"
;
const
app
=
new
Hono
(
)
;
const
userSchema
=
z
.
object
(
{
name
:
z
.
string
(
)
.
min
(
1
)
,
email
:
z
.
string
(
)
.
email
(
)
,
age
:
z
.
number
(
)
.
min
(
0
)
.
optional
(
)
,
}
)
;
app
.
post
(
"/users"
,
zValidator
(
"json"
,
userSchema
)
,
(
c
)
=>
{
const
user
=
c
.
req
.
valid
(
"json"
)
;
// user is typed and validated
return
c
.
json
(
{
created
:
user
}
)
;
}
)
;
// Query validation
const
querySchema
=
z
.
object
(
{
page
:
z
.
string
(
)
.
regex
(
/
^
\d
+
$
/
)
.
optional
(
)
,
limit
:
z
.
string
(
)
.
regex
(
/
^
\d
+
$
/
)
.
optional
(
)
,
}
)
;
app
.
get
(
"/items"
,
zValidator
(
"query"
,
querySchema
)
,
(
c
)
=>
{
const
{
page
,
limit
}
=
c
.
req
.
valid
(
"query"
)
;
return
c
.
json
(
{
page
,
limit
}
)
;
}
)
;
export
default
app
;
Context Variables
import
{
Hono
}
from
"hono"
;
type
Variables
=
{
userId
:
string
;
isAdmin
:
boolean
;
}
;
const
app
=
new
Hono
<
{
Variables
:
Variables
}
( ) ; app . use ( "*" , async ( c , next ) => { c . set ( "userId" , "123" ) ; c . set ( "isAdmin" , true ) ; await next ( ) ; } ) ; app . get ( "/profile" , ( c ) => { const userId = c . get ( "userId" ) ; const isAdmin = c . get ( "isAdmin" ) ; return c . json ( { userId , isAdmin } ) ; } ) ; export default app ; Error Handling import { Hono } from "hono" ; import { HTTPException } from "hono/http-exception" ; const app = new Hono ( ) ; // Throw HTTP error app . get ( "/error" , ( c ) => { throw new HTTPException ( 401 , { message : "Unauthorized" } ) ; } ) ; // Global error handler app . onError ( ( err , c ) => { if ( err instanceof HTTPException ) { return err . getResponse ( ) ; } console . error ( err ) ; return c . json ( { error : "Internal Server Error" } , 500 ) ; } ) ; // Not found handler app . notFound ( ( c ) => { return c . json ( { error : "Not Found" } , 404 ) ; } ) ; export default app ; RPC Mode (Type-safe Client) // server.ts import { Hono } from "hono" ; import { hc } from "hono/client" ; const app = new Hono ( ) . get ( "/users" , ( c ) => c . json ( [ { id : 1 , name : "Alice" } ] ) ) . post ( "/users" , async ( c ) => { const body = await c . req . json ( ) ; return c . json ( { created : body } ) ; } ) ; export type AppType = typeof app ; export default app ; // client.ts import { hc } from "hono/client" ; import type { AppType } from "./server" ; const client = hc < AppType
( "http://localhost:3000" ) ; // Type-safe calls const res = await client . users . $get ( ) ; const users = await res . json ( ) ; // Typed! const created = await client . users . $post ( { json : { name : "Bob" } , } ) ; Common Errors Error Cause Fix Route not found Wrong path Check route registration Body already read Double parsing Read body once Validator error Invalid input Check schema definition Middleware order Wrong execution Register middleware first When to Load References Load references/middleware-list.md when: Complete middleware reference Custom middleware patterns Load references/openapi.md when: OpenAPI/Swagger integration API documentation generation