Public evidence: generated by OpenThunder’s keyless engine (no AI) from honojs/hono@5ca49b0 on 2026-10-19. Reproduce it: openthunder lens generate --no-narrate && openthunder lens export. ← Evidence Gallery

hono: Architecture

hono · 5ca49b072075 · generated 2026-10-19T06:56:59.066Z · static analysis

Architecture health: 49/100 (F)

Overview

hono is a JavaScript/TypeScript pnpm monorepo, built with React and Express. The main structural risks to watch: 5 oversized "god" files and 3 circular import chains. The file with the widest blast radius is src/types.ts: types used by 54 modules; oversized and doing too much.

_This entire analysis runs on your machine with no AI required. Connect a model provider to also narrate the reasoning and recover decisions._

Where to start

  1. src/context.ts Core module: 73 other modules depend on it, so it shapes much of the system.
  2. src/hono.ts Core module: 69 other modules depend on it, so it shapes much of the system.
  3. src/types.ts Core module: 63 other modules depend on it, so it shapes much of the system.
  4. src/router.ts Core module: 21 other modules depend on it, so it shapes much of the system.
  5. src/utils/basic-auth.ts Key flow: Authentication, a high-risk path that enters at invoke basic-auth.ts (src/utils/basic-auth.ts).
  6. src/middleware/secure-headers/permissions-policy.ts Key flow: Mission execution, a high-risk path that enters at invoke permissions-policy.ts (src/middleware/secure-headers/permissions-policy.ts).
  7. src/helper/streaming/index.ts Key flow: AI provider call, a high-risk path that enters at invoke index.ts (src/helper/streaming/index.ts).
  8. benchmarks/http-server/benchmark.ts Key flow: File changes / writes, a high-risk path that enters at invoke benchmark.ts (benchmarks/http-server/benchmark.ts).
  9. src/jsx/base.ts Change with care: 8 files depend on it at runtime; types used by 9 modules; part of an import cycle.

System map

flowchart TD
  subgraph sys_boundary["hono"]
  end
  classDef frontend fill:#2563eb,stroke:#93c5fd,color:#fff,stroke-width:2px;
  classDef service fill:#059669,stroke:#6ee7b7,color:#fff,stroke-width:2px;
  classDef store fill:#d97706,stroke:#fcd34d,color:#fff,stroke-width:2px;
  classDef queue fill:#9333ea,stroke:#d8b4fe,color:#fff,stroke-width:2px;
  classDef job fill:#4f46e5,stroke:#a5b4fc,color:#fff,stroke-width:2px;
  classDef external fill:#475569,stroke:#cbd5e1,color:#fff,stroke-width:2px;
  classDef aiprovider fill:#e11d48,stroke:#fda4af,color:#fff,stroke-width:2px;
  classDef library fill:#0891b2,stroke:#67e8f9,color:#fff,stroke-width:2px;
  classDef cli fill:#0d9488,stroke:#5eead4,color:#fff,stroke-width:2px;
  classDef user fill:#64748b,stroke:#e2e8f0,color:#fff,stroke-width:2px;
  classDef muted fill:#334155,stroke:#64748b,color:#cbd5e1,stroke-width:1px;

Critical flows

Authentication high risk

Entry: invoke basic-auth.ts (src/utils/basic-auth.ts)

Authentication guards every protected resource; a regression here can expose data or grant unauthorized access.

sequenceDiagram
  actor C0 as Caller
  participant F0 as basic-auth.ts
  participant F1 as src/types.ts
  participant F2 as aws-lambda/types.ts
  participant F3 as cookie/index.ts
  participant F4 as basic-auth/index.ts
  participant F5 as bearer-auth/index.ts
  C0->>F0: invoke basic-auth.ts

Mission execution high risk

Entry: invoke permissions-policy.ts (src/middleware/secure-headers/permissions-policy.ts)

Mission execution drives autonomous code changes; errors here corrupt runs or the target repository.

sequenceDiagram
  actor C0 as Caller
  participant F0 as permissions-policy.ts
  C0->>F0: invoke permissions-policy.ts

AI provider call high risk

Entry: invoke index.ts (src/helper/streaming/index.ts)

sends a prompt and receives a completion (AI provider)

Provider calls cost money and shape model output; mistakes leak prompts, burn budget, or route to the wrong model.

sequenceDiagram
  actor C0 as Caller
  participant F0 as index.ts
  participant F1 as text.ts
  participant AI as AI provider
  C0->>F0: invoke index.ts
  F0->>AI: sends a prompt and receives a completion
  F0->>F1: calls
  F1->>AI: sends a prompt and receives a completion

File changes / writes high risk

Entry: invoke benchmark.ts (benchmarks/http-server/benchmark.ts)

writes files to the working tree (disk); calls an external service (external API)

Direct writes to the working tree are hard to reverse; an unguarded write can clobber user code.

sequenceDiagram
  actor C0 as Caller
  participant F0 as benchmark.ts
  participant F1 as src/ssg.ts
  participant F2 as src/ssg.ts
  participant F3 as check-bundle-size.ts
  participant F4 as generate-app.ts
  participant F5 as bun/ssg.ts
  participant Disk as disk
  participant External as external API
  C0->>F0: invoke benchmark.ts
  F0->>Disk: writes files to the working tree
  F0->>External: calls an external service
  F1->>Disk: writes files to the working tree
  F2->>Disk: writes files to the working tree
  F3->>Disk: writes files to the working tree
  F4->>Disk: writes files to the working tree
  F5->>Disk: writes files to the working tree

Background jobs medium risk

Entry: GET / (runtime-tests/workerd/index.ts)

calls an external service (external API); returns a response to the caller (client)

Background jobs run unattended; failures are silent and can pile up unnoticed.

sequenceDiagram
  actor C0 as Scheduler
  participant F0 as workerd/index.ts
  participant F1 as conninfo.ts
  participant F2 as src/index.ts
  participant F3 as serve-static-module.ts
  participant F4 as serve-static.ts
  participant F5 as utils.ts
  C0->>F0: GET /

Fragile zones

Architecture rules

blocking Change src/types.ts with care: types used by 54 modules; oversized and doing too much. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 63, fan-out 5, risk score 58); a careless edit ripples through many dependents.

blocking Change src/context.ts with care: 7 files depend on it at runtime; types used by 34 modules; oversized and doing too much. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 73, fan-out 8, risk score 52.5); a careless edit ripples through many dependents.

blocking Change src/jsx/base.ts with care: 8 files depend on it at runtime; types used by 9 modules; part of an import cycle. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 18, fan-out 8, risk score 31.8); a careless edit ripples through many dependents.

blocking Change src/jsx/context.ts with care: 10 files depend on it at runtime; part of an import cycle. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 13, fan-out 5, risk score 27); a careless edit ripples through many dependents.

blocking Change src/jsx/constants.ts with care: 13 files depend on it at runtime. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 14, fan-out 0, risk score 26); a careless edit ripples through many dependents.

blocking Change src/router.ts with care: 11 files depend on it at runtime. Preserve its public signatures, keep changes additive where possible, and run/extend its tests before and after.

This file has a wide blast radius (fan-in 21, fan-out 0, risk score 26); a careless edit ripples through many dependents.

warning Do not add imports that deepen existing import cycles (e.g. src/jsx/base.ts → src/jsx/context.ts → src/jsx/dom/context.ts → …). Break cycles when you touch the files involved.

Circular dependencies make modules impossible to reason about or test in isolation and cause load-order bugs.

advisory Do not add new responsibilities to oversized files (src/types.ts, src/jsx/dom/render.ts, src/context.ts, src/jsx/intrinsic-elements.ts, src/adapter/aws-lambda/handler.ts); extract new logic into focused modules instead.

Large multi-purpose files are change magnets that accumulate coupling and resist testing; keeping them from growing limits the damage.

warning Respect package boundaries: import across packages via their published entry (e.g. the package name), not deep relative paths reaching into another package's internals.

Deep cross-package imports defeat the module boundary, make refactors brittle, and create hidden coupling the build graph cannot see.