Public Wiki28,688View on GitHub
Want honojs/hono knowledge in your AI?

src

Hono is a lightweight, multi-runtime web framework for building HTTP APIs and web applications. It provides a complete stack including routing, middleware, JSX rendering (both server-side and client-side), a type-safe RPC client, and request validation — all designed to run on Cloudflare Workers, Deno, Bun, AWS Lambda, Vercel, Netlify, Node.js, and Service Workers with zero runtime-specific lock-in.

Tech Stack

ReactVitestZod

Key Features

  • Multi-Algorithm Router System
  • Middleware Composition Engine
  • Multi-Runtime Adapters
  • Built-in JSX Engine with SSR and Client-Side DOM
  • Type-Safe RPC Client (hc)
  • Request Validation Framework
  • Built-in Security & Auth Middleware
  • Helper Utilities
  • Router Presets

Entry Points

Start here when working with this codebase

index.ts
src/index.ts

Application entry point

Start here to understand how the application initializes

Coding Conventions

Standards and patterns used in this codebase

TypeScript

Use extensive generic type parameters for type-safe routing, middleware composition, and request/response handling. Types are deeply nested and leverage conditional types, mapped types, and template literal types for full inference.

class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'>
src/types.tssrc/hono-base.tssrc/hono.ts
TypeScript

Disable TypeScript type-checking ESLint rules (no @typescript-eslint/recommended-type-checked) in favor of relying on the TypeScript compiler itself for type safety.

tseslint.configs.recommended (not recommended-type-checked)
eslint.config.mjs
Architecture

Follow a strategy pattern for routers: define a common Router interface and provide multiple implementations (RegExp, Trie, Smart, Linear, Pattern) that can be swapped via presets.

export interface Router<T> { name: string; add(method: string, path: string, handler: T): void; match(method: string, path: string): Result<T>; }
src/router.tssrc/preset
Middleware

Compose middleware using a koa-compose pattern where each middleware calls `await next()` to pass control to the next handler, with error handling wrapping the entire chain.

const composed = compose<Context>(middleware, onError, onNotFound)
src/compose.tssrc/hono-base.ts
Module Structure

Use barrel exports (index.ts) as the public API surface, re-exporting only the intended public types and classes. Internal implementation details are not exported from the main entry point.

export { Hono } from './hono'; export type { Context } from './context';
src/index.ts
Error Handling

Use a custom HTTPException class that extends Error, carrying HTTP status codes and optional Response objects, enabling structured error responses throughout the framework.

throw new HTTPException(401, { message: 'Unauthorized', res: unauthorizedResponse })
src/http-exception.tssrc/hono-base.ts
API Design

Context class provides a fluent, chainable API with shorthand methods for common response types (json, text, html, redirect, body, header, status) that return Response objects.

return c.json({ message: 'hello' }, 200)
src/context.ts
Testing

Use Vitest as the test framework with multiple test projects configured for different JSX runtimes and environments. Coverage is configured with v8 provider.

projects: [{ test: { include: ['src/**/*.test.ts'] } }, { test: { include: ['src/jsx/**/*.test.ts'] } }]
vitest.config.ts
Runtime Compatibility

Design for multi-runtime support (Bun, Deno, Node, Cloudflare Workers, AWS Lambda, etc.) by using Web Standard APIs (Request, Response, fetch) as the common interface, with thin runtime-specific adapters.

export const handle = (app: Hono) => (req: Request) => app.fetch(req)
src/adaptersrc/hono-base.ts
Code Style

Prefer immutable patterns and lazy evaluation. Request parsing methods (query, param, json, formData) use lazy getters with caching to avoid redundant parsing.

get query() { return this.#query ??= Object.fromEntries(new URL(this.url).searchParams) }
src/request.tssrc/context.ts
Naming

Use single-letter or short generic type parameter names following conventions: E for Env, S for Schema, P for Path, I for Input, R for Response, H for Handler.

type Handler<E extends Env = any, P extends string = any, I extends Input = {}, R extends HandlerResponse<any> = any>
src/types.ts
Code Style

Use private class fields (# syntax) for internal state rather than TypeScript's private keyword.

#body: BodyInit | null; #notFoundHandler: NotFoundHandler; #path: string = '/';
src/context.tssrc/request.tssrc/hono-base.ts