Hono logoHono INTERMEDIATE

Hono

Comprehensive Hono cheat sheet covering routing, middleware, context, validation, RPC client, streaming, and deployment across Cloudflare Workers, Bun, Deno, and Node.js.

5 min read
honoweb-frameworkcloudflare-workersbundenonodejstypescriptapiedgeserverless

Getting Started

Create a New Project

Initialize a Hono project with create-hono CLI

bash
💡 Hono works on any JavaScript runtime with Web Standards support
⚡ Zero dependencies - ultrafast and lightweight (~14KB)
📌 TypeScript types are included - no @types package needed
🔥 Use Bun for fastest local development experience

Basic Hello World

Create your first Hono application

typescript
💡 The context object "c" provides all request/response utilities
⚡ c.text(), c.json(), c.html() - common response helpers
📌 Export default for Cloudflare Workers and Bun
🎯 Hono uses Web Standard Request/Response APIs

Routing

HTTP Methods & Paths

Define routes for different HTTP methods

typescript
💡 Use app.all() to match any HTTP method
⚡ Wildcards: * matches one segment, trailing * matches all
📌 app.on() for custom methods or multiple methods
🎯 Use app.route() for modular route grouping

Path Parameters

Extract dynamic values from URLs

typescript
💡 c.req.param("name") gets single param, c.req.param() gets all
⚡ Use regex patterns for validation: :id{[0-9]+}
📌 Wildcard * captures everything after the path segment
🎯 Optional params: :param? matches with or without

Route Groups & Basepath

Organize routes with grouping and base paths

typescript
💡 Use .basePath() to prefix all routes in an app
⚡ app.route(path, subApp) mounts sub-apps at a path
📌 Chain methods for proper RPC type inference
🎯 Export typeof app for type-safe RPC client

Context & Request

Request Data

Access query params, headers, body, and more

typescript
💡 c.req.query() for single, c.req.queries() for arrays
⚡ Body methods are async: await c.req.json()
📌 Headers are case-insensitive
🎯 Use getCookie from "hono/cookie" for cookies

Response Methods

Different ways to send responses

typescript
💡 c.json(), c.text(), c.html() are convenience methods
⚡ Pass status code as second argument: c.json(data, 201)
📌 Use c.header() to set response headers
🎯 Import cookie helpers from "hono/cookie"

Context Variables

Store and retrieve values in request context

typescript
💡 c.set(key, value) stores, c.get(key) retrieves
⚡ Use generics for type-safe context variables
📌 Bindings are for environment variables (Cloudflare)
🎯 Variables persist throughout the request lifecycle

Middleware

Creating Middleware

Define and use custom middleware

typescript
💡 Always call await next() to continue the chain
⚡ Middleware runs before handler, after next() returns
📌 Use createMiddleware from "hono/factory" for types
🎯 Return a response to short-circuit the chain

Built-in Middleware

Common middleware included with Hono

typescript
💡 logger() adds request/response logging
⚡ cors() handles CORS preflight automatically
📌 secureHeaders() adds security headers (CSP, etc.)
🎯 compress() gzips responses for smaller payloads

Authentication Middleware

Basic Auth, Bearer Auth, and JWT middleware

typescript
💡 basicAuth sends WWW-Authenticate header on failure
⚡ bearerAuth expects "Authorization: Bearer <token>" header
📌 JWT payload accessible via c.get("jwtPayload")
🎯 Use sign() from "hono/jwt" to create tokens

Validation

Zod Validation

Type-safe validation with Zod schemas

typescript
💡 Install: npm install @hono/zod-validator zod
⚡ Targets: json, query, param, header, form, cookie
📌 Use z.coerce for automatic type conversion
🎯 c.req.valid("target") returns typed validated data

Built-in Validator

Use Hono's built-in validator without external deps

typescript
💡 Built-in validator works without external libraries
⚡ Return c.json() or c.text() to short-circuit with error
📌 Return validated data to pass to handler
🎯 Supports async validation for database checks

RPC Client

Type-Safe Client

Create a type-safe API client from your Hono app

typescript
💡 Chain methods (.get().post()) for proper type inference
⚡ Export "typeof app" as AppType for client usage
📌 Validation schemas are reflected in client types
🎯 Works with route groups via .route()

Client Usage

Use the type-safe RPC client

typescript
💡 hc<AppType>(baseUrl) creates typed client
⚡ Path params: client.users[":id"].$get({ param: {} })
📌 JSON body: $post({ json: {} }), query: $get({ query: {} })
🎯 InferRequestType/InferResponseType for type extraction

Streaming & SSE

Server-Sent Events

Stream real-time updates to clients

typescript
💡 streamSSE automatically sets correct SSE headers
⚡ Use stream.sleep(ms) for intervals, not setTimeout
📌 stream.onAbort() handles client disconnection
🎯 Client uses EventSource API for SSE

WebSockets

Real-time bidirectional communication

typescript
💡 Import upgradeWebSocket from runtime-specific path
⚡ Bun requires exporting websocket with app.fetch
📌 onOpen not supported on Cloudflare Workers
🎯 Use RPC mode for type-safe WebSocket client

Error Handling

HTTPException & Error Handlers

Handle errors gracefully in your app

typescript
💡 HTTPException creates standard HTTP error responses
⚡ app.onError() catches all unhandled errors
📌 Route-level onError takes precedence over global
🎯 app.notFound() handles 404s

Deployment

Cloudflare Workers

Deploy to Cloudflare Workers edge network

typescript
💡 Use Bindings type for type-safe environment access
⚡ Access bindings via c.env in handlers
📌 .dev.vars for local secrets (add to .gitignore)
🎯 npx wrangler deploy for production

Bun, Deno & Node.js

Deploy to other JavaScript runtimes

typescript
💡 Bun: export default app or { port, fetch }
⚡ Deno: Deno.serve(app.fetch)
📌 Node: npm install @hono/node-server
🎯 Vercel/Lambda: use handle() adapter

Testing

Testing with app.request()

Test your Hono app without starting a server

typescript
💡 app.request() returns a real Response object
⚡ No server needed - tests run in memory
📌 Pass third argument for Cloudflare bindings/env
🎯 Works with Vitest, Jest, or any test runner