litclaude-ai 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +155 -0
- package/LICENSE +21 -0
- package/README.md +369 -0
- package/README_ko-KR.md +374 -0
- package/RELEASE_CHECKLIST.md +165 -0
- package/bin/litclaude-ai.js +643 -0
- package/cover.png +0 -0
- package/docs/agents.md +67 -0
- package/docs/hooks.md +134 -0
- package/docs/lsp.md +40 -0
- package/docs/migration.md +209 -0
- package/docs/workflow-compatibility-audit.md +119 -0
- package/generate_cover.py +123 -0
- package/package.json +48 -0
- package/plugins/litclaude/.claude-plugin/plugin.json +25 -0
- package/plugins/litclaude/.lsp.json +13 -0
- package/plugins/litclaude/.mcp.json +9 -0
- package/plugins/litclaude/agents/boulder-executor.md +12 -0
- package/plugins/litclaude/agents/librarian-researcher.md +15 -0
- package/plugins/litclaude/agents/oracle-verifier.md +16 -0
- package/plugins/litclaude/agents/prometheus-planner.md +13 -0
- package/plugins/litclaude/agents/qa-runner.md +16 -0
- package/plugins/litclaude/agents/quality-reviewer.md +17 -0
- package/plugins/litclaude/bin/litclaude-hook.js +110 -0
- package/plugins/litclaude/bin/litclaude-hud.js +271 -0
- package/plugins/litclaude/bin/litclaude-lsp-doctor.js +15 -0
- package/plugins/litclaude/bin/litclaude-mcp.js +70 -0
- package/plugins/litclaude/commands/deep-interview.md +21 -0
- package/plugins/litclaude/commands/dynamic-workflow.md +36 -0
- package/plugins/litclaude/commands/lit-loop.md +40 -0
- package/plugins/litclaude/commands/lit-plan.md +35 -0
- package/plugins/litclaude/commands/litgoal.md +30 -0
- package/plugins/litclaude/commands/review-work.md +35 -0
- package/plugins/litclaude/commands/start-work.md +36 -0
- package/plugins/litclaude/hooks/hooks.json +54 -0
- package/plugins/litclaude/lib/context-pressure.mjs +25 -0
- package/plugins/litclaude/lib/hud-accent-palette.mjs +58 -0
- package/plugins/litclaude/lib/litgoal/cli.mjs +266 -0
- package/plugins/litclaude/lib/litgoal/ledger.mjs +16 -0
- package/plugins/litclaude/lib/litgoal/paths.mjs +7 -0
- package/plugins/litclaude/lib/litgoal/state.mjs +67 -0
- package/plugins/litclaude/lib/mutated-file-paths.mjs +63 -0
- package/plugins/litclaude/lib/start-work-continuation.mjs +99 -0
- package/plugins/litclaude/lib/workflow-check.mjs +83 -0
- package/plugins/litclaude/skills/ai-slop-remover/SKILL.md +142 -0
- package/plugins/litclaude/skills/comment-checker/SKILL.md +55 -0
- package/plugins/litclaude/skills/debugging/SKILL.md +70 -0
- package/plugins/litclaude/skills/debugging/references/methodology/00-setup.md +108 -0
- package/plugins/litclaude/skills/debugging/references/methodology/02-investigate.md +126 -0
- package/plugins/litclaude/skills/debugging/references/methodology/04-oracle-triple.md +106 -0
- package/plugins/litclaude/skills/debugging/references/methodology/05-escalate.md +69 -0
- package/plugins/litclaude/skills/debugging/references/methodology/06-fix.md +116 -0
- package/plugins/litclaude/skills/debugging/references/methodology/08-qa.md +94 -0
- package/plugins/litclaude/skills/debugging/references/methodology/09-cleanup.md +164 -0
- package/plugins/litclaude/skills/debugging/references/methodology/partial-runtime-evidence.md +228 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/bundled-js-binary.md +415 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/go.md +252 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/native-binary.md +484 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/node.md +260 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/python.md +248 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/rust.md +234 -0
- package/plugins/litclaude/skills/debugging/references/tools/ghidra.md +212 -0
- package/plugins/litclaude/skills/debugging/references/tools/playwright-cli.md +194 -0
- package/plugins/litclaude/skills/debugging/references/tools/pwndbg.md +263 -0
- package/plugins/litclaude/skills/debugging/references/tools/pwntools.md +265 -0
- package/plugins/litclaude/skills/deep-interview/SKILL.md +323 -0
- package/plugins/litclaude/skills/deep-interview/scripts/render_progress.py +193 -0
- package/plugins/litclaude/skills/frontend-ui-ux/SKILL.md +62 -0
- package/plugins/litclaude/skills/lit-loop/SKILL.md +144 -0
- package/plugins/litclaude/skills/lit-plan/SKILL.md +125 -0
- package/plugins/litclaude/skills/litgoal/SKILL.md +219 -0
- package/plugins/litclaude/skills/lsp/SKILL.md +63 -0
- package/plugins/litclaude/skills/programming/SKILL.md +106 -0
- package/plugins/litclaude/skills/programming/references/go/README.md +90 -0
- package/plugins/litclaude/skills/programming/references/go/backend-stack.md +641 -0
- package/plugins/litclaude/skills/programming/references/go/bootstrap.md +328 -0
- package/plugins/litclaude/skills/programming/references/go/bubbletea-v2.md +360 -0
- package/plugins/litclaude/skills/programming/references/go/cobra-stack.md +468 -0
- package/plugins/litclaude/skills/programming/references/go/concurrency.md +362 -0
- package/plugins/litclaude/skills/programming/references/go/data-modeling.md +329 -0
- package/plugins/litclaude/skills/programming/references/go/error-handling.md +359 -0
- package/plugins/litclaude/skills/programming/references/go/golangci-strict.md +236 -0
- package/plugins/litclaude/skills/programming/references/go/grpc-connect.md +375 -0
- package/plugins/litclaude/skills/programming/references/go/libraries.md +337 -0
- package/plugins/litclaude/skills/programming/references/go/one-liners.md +202 -0
- package/plugins/litclaude/skills/programming/references/go/sqlc-pgx.md +471 -0
- package/plugins/litclaude/skills/programming/references/go/testing.md +467 -0
- package/plugins/litclaude/skills/programming/references/go/type-patterns.md +298 -0
- package/plugins/litclaude/skills/programming/references/python/README.md +314 -0
- package/plugins/litclaude/skills/programming/references/python/async-anyio.md +442 -0
- package/plugins/litclaude/skills/programming/references/python/data-modeling.md +233 -0
- package/plugins/litclaude/skills/programming/references/python/data-processing.md +133 -0
- package/plugins/litclaude/skills/programming/references/python/error-handling.md +218 -0
- package/plugins/litclaude/skills/programming/references/python/fastapi-stack.md +316 -0
- package/plugins/litclaude/skills/programming/references/python/httpx2-optimization.md +360 -0
- package/plugins/litclaude/skills/programming/references/python/libraries.md +307 -0
- package/plugins/litclaude/skills/programming/references/python/one-liners.md +268 -0
- package/plugins/litclaude/skills/programming/references/python/orjson-stack.md +378 -0
- package/plugins/litclaude/skills/programming/references/python/pydantic-ai.md +285 -0
- package/plugins/litclaude/skills/programming/references/python/pyproject-strict.md +232 -0
- package/plugins/litclaude/skills/programming/references/python/textual-tui.md +201 -0
- package/plugins/litclaude/skills/programming/references/python/type-patterns.md +176 -0
- package/plugins/litclaude/skills/programming/references/rust/README.md +317 -0
- package/plugins/litclaude/skills/programming/references/rust/async-tokio.md +299 -0
- package/plugins/litclaude/skills/programming/references/rust/axum-stack.md +467 -0
- package/plugins/litclaude/skills/programming/references/rust/cargo-strict.md +317 -0
- package/plugins/litclaude/skills/programming/references/rust/clap-stack.md +409 -0
- package/plugins/litclaude/skills/programming/references/rust/concurrency.md +375 -0
- package/plugins/litclaude/skills/programming/references/rust/libraries.md +439 -0
- package/plugins/litclaude/skills/programming/references/rust/one-liners.md +291 -0
- package/plugins/litclaude/skills/programming/references/rust/proptest-insta.md +429 -0
- package/plugins/litclaude/skills/programming/references/rust/type-state.md +354 -0
- package/plugins/litclaude/skills/programming/references/rust/unsafe-discipline.md +250 -0
- package/plugins/litclaude/skills/programming/references/rust/zero-cost-safety.md +527 -0
- package/plugins/litclaude/skills/programming/references/rust-ub/README.md +289 -0
- package/plugins/litclaude/skills/programming/references/rust-ub/miri-sanitizers-loom.md +411 -0
- package/plugins/litclaude/skills/programming/references/rust-ub/ub-taxonomy.md +269 -0
- package/plugins/litclaude/skills/programming/references/typescript/README.md +195 -0
- package/plugins/litclaude/skills/programming/references/typescript/backend-hono.md +672 -0
- package/plugins/litclaude/skills/programming/references/typescript/bootstrap.md +199 -0
- package/plugins/litclaude/skills/programming/references/typescript/data-modeling.md +202 -0
- package/plugins/litclaude/skills/programming/references/typescript/error-handling.md +169 -0
- package/plugins/litclaude/skills/programming/references/typescript/tsconfig-strict.md +152 -0
- package/plugins/litclaude/skills/programming/references/typescript/type-patterns.md +196 -0
- package/plugins/litclaude/skills/programming/scripts/go/check-no-excuse-rules.sh +173 -0
- package/plugins/litclaude/skills/programming/scripts/go/new-project.py +138 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/.editorconfig +13 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/.golangci.yml +95 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/AGENTS.md.tmpl +24 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/README.md.tmpl +12 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/Taskfile.yml +40 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/ci.yml +37 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/config.go +24 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/gitignore +15 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/main.go.tmpl +22 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/run.go +15 -0
- package/plugins/litclaude/skills/programming/scripts/python/check-no-excuse-rules.py +687 -0
- package/plugins/litclaude/skills/programming/scripts/python/new-project.py +172 -0
- package/plugins/litclaude/skills/programming/scripts/python/new-script.py +116 -0
- package/plugins/litclaude/skills/programming/scripts/rust/check-no-excuse-rules.py +296 -0
- package/plugins/litclaude/skills/programming/scripts/rust/check-no-excuse-rules.sh +158 -0
- package/plugins/litclaude/skills/programming/scripts/rust/new-project.py +175 -0
- package/plugins/litclaude/skills/programming/scripts/typescript/check-no-excuse-rules.ts +282 -0
- package/plugins/litclaude/skills/programming/scripts/typescript/new-project.ts +177 -0
- package/plugins/litclaude/skills/refactor/SKILL.md +73 -0
- package/plugins/litclaude/skills/remove-ai-slops/SKILL.md +52 -0
- package/plugins/litclaude/skills/review-work/SKILL.md +331 -0
- package/plugins/litclaude/skills/rules/SKILL.md +66 -0
- package/plugins/litclaude/skills/start-work/SKILL.md +132 -0
- package/scripts/audit-plan-checkboxes.mjs +37 -0
- package/scripts/doctor.mjs +41 -0
- package/scripts/inspect-agent-tools.mjs +27 -0
- package/scripts/postinstall.mjs +50 -0
- package/scripts/qa-claude-plugin-smoke.sh +60 -0
- package/scripts/qa-portable-install.sh +136 -0
- package/scripts/validate-plugin.mjs +72 -0
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
# Hono Backend Stack Reference (2026)
|
|
2
|
+
|
|
3
|
+
> **Canonical stack**: `hono` + `hono-openapi` + `@scalar/hono-api-reference` + `@hono/swagger-ui`
|
|
4
|
+
> **Runtime**: Bun (TypeScript-first)
|
|
5
|
+
> **Validator**: Zod v4 (Standard Schema compliant, zero extra deps for OpenAPI)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Package Versions (Latest Stable)
|
|
10
|
+
|
|
11
|
+
| Package | Version | Source |
|
|
12
|
+
|---------|---------|--------|
|
|
13
|
+
| `hono` | `^4.12.5` | [peer dep of scalar](https://github.com/scalar/scalar/blob/8bcf8bf52a0da667d44eeec08648e3b1da044f97/integrations/hono/package.json#L66) |
|
|
14
|
+
| `hono-openapi` | `^1.3.0` | [npm](https://registry.npmjs.org/hono-openapi) — published Mar 2, 2026 |
|
|
15
|
+
| `@scalar/hono-api-reference` | `^0.10.11` | [npm](https://www.npmjs.com/package/@scalar/hono-api-reference) — published Apr 28, 2026 |
|
|
16
|
+
| `@hono/swagger-ui` | `^0.6.1` | [npm](https://www.npmjs.com/package/@hono/swagger-ui) — published Apr 2026 |
|
|
17
|
+
| `zod` | `^4.4.1` | [npm registry](https://registry.npmjs.org/zod) — latest stable v4 |
|
|
18
|
+
|
|
19
|
+
### `package.json` dependency block
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"hono": "^4.12.5",
|
|
25
|
+
"hono-openapi": "^1.3.0",
|
|
26
|
+
"@scalar/hono-api-reference": "^0.10.11",
|
|
27
|
+
"@hono/swagger-ui": "^0.6.1",
|
|
28
|
+
"zod": "^4.4.1"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"typescript": "^5.8.0",
|
|
32
|
+
"@types/bun": "latest"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> **Peer dependencies auto-installed by `hono-openapi`**:
|
|
38
|
+
> - `@hono/standard-validator@^0.2.0`
|
|
39
|
+
> - `@standard-community/standard-json@^0.3.5`
|
|
40
|
+
> - `@standard-community/standard-openapi@^0.2.9`
|
|
41
|
+
> - `openapi-types@^12.1.3`
|
|
42
|
+
>
|
|
43
|
+
> [Source: `hono-openapi/package.json` peerDependencies](https://github.com/rhinobase/hono-openapi/blob/10f45a66ede3764b5e6065805fb60fd5df090466/package.json#L50-L65)
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. Complete `app.ts` — Copy-Pasteable
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { Hono } from 'hono'
|
|
51
|
+
import { describeRoute, openAPIRouteHandler, resolver, validator } from 'hono-openapi'
|
|
52
|
+
import { Scalar } from '@scalar/hono-api-reference'
|
|
53
|
+
import { swaggerUI } from '@hono/swagger-ui'
|
|
54
|
+
import { z } from 'zod'
|
|
55
|
+
|
|
56
|
+
// ───────────────────────────────────────────────────────────────
|
|
57
|
+
// 1. Schema definitions (Zod v4 — Standard Schema native)
|
|
58
|
+
// ───────────────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
const QuerySchema = z.object({
|
|
61
|
+
name: z.string().optional(),
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const ResponseSchema = z.object({
|
|
65
|
+
message: z.string(),
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const JsonBodySchema = z.object({
|
|
69
|
+
name: z.string(),
|
|
70
|
+
age: z.number().int().min(0),
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// ───────────────────────────────────────────────────────────────
|
|
74
|
+
// 2. Hono app with described routes
|
|
75
|
+
// ───────────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
const app = new Hono()
|
|
78
|
+
|
|
79
|
+
// Health check (no validation)
|
|
80
|
+
app.get('/health', (c) => c.json({ status: 'ok' }))
|
|
81
|
+
|
|
82
|
+
// A fully-documented route
|
|
83
|
+
app.get(
|
|
84
|
+
'/hello',
|
|
85
|
+
describeRoute({
|
|
86
|
+
tags: ['Greetings'],
|
|
87
|
+
summary: 'Say hello',
|
|
88
|
+
description: 'Returns a greeting message',
|
|
89
|
+
responses: {
|
|
90
|
+
200: {
|
|
91
|
+
description: 'Successful greeting',
|
|
92
|
+
content: {
|
|
93
|
+
'application/json': {
|
|
94
|
+
schema: resolver(ResponseSchema),
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
100
|
+
validator('query', QuerySchema),
|
|
101
|
+
(c) => {
|
|
102
|
+
const query = c.req.valid('query')
|
|
103
|
+
return c.json({ message: `Hello ${query.name ?? 'Hono'}!` })
|
|
104
|
+
},
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
// A POST route with JSON body validation
|
|
108
|
+
app.post(
|
|
109
|
+
'/users',
|
|
110
|
+
describeRoute({
|
|
111
|
+
tags: ['Users'],
|
|
112
|
+
summary: 'Create a user',
|
|
113
|
+
responses: {
|
|
114
|
+
200: {
|
|
115
|
+
description: 'User created',
|
|
116
|
+
content: {
|
|
117
|
+
'application/json': {
|
|
118
|
+
schema: resolver(ResponseSchema),
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
}),
|
|
124
|
+
validator('json', JsonBodySchema),
|
|
125
|
+
(c) => {
|
|
126
|
+
const body = c.req.valid('json')
|
|
127
|
+
return c.json({ message: `Created user ${body.name}` })
|
|
128
|
+
},
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
// ───────────────────────────────────────────────────────────────
|
|
132
|
+
// 3. OpenAPI spec endpoint
|
|
133
|
+
// ───────────────────────────────────────────────────────────────
|
|
134
|
+
|
|
135
|
+
app.get(
|
|
136
|
+
'/openapi.json',
|
|
137
|
+
openAPIRouteHandler(app, {
|
|
138
|
+
documentation: {
|
|
139
|
+
info: {
|
|
140
|
+
title: 'Hono API',
|
|
141
|
+
version: '1.0.0',
|
|
142
|
+
description: 'Example Hono API with OpenAPI',
|
|
143
|
+
},
|
|
144
|
+
servers: [
|
|
145
|
+
{ url: 'http://localhost:3000', description: 'Local server' },
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
}),
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
// ───────────────────────────────────────────────────────────────
|
|
152
|
+
// 4. Scalar API Reference UI
|
|
153
|
+
// ───────────────────────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
app.get(
|
|
156
|
+
'/scalar',
|
|
157
|
+
Scalar({
|
|
158
|
+
url: '/openapi.json',
|
|
159
|
+
theme: 'saturn',
|
|
160
|
+
pageTitle: 'Hono API Reference',
|
|
161
|
+
}),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
// ───────────────────────────────────────────────────────────────
|
|
165
|
+
// 5. Swagger UI (parallel mount)
|
|
166
|
+
// ───────────────────────────────────────────────────────────────
|
|
167
|
+
|
|
168
|
+
app.get(
|
|
169
|
+
'/swagger',
|
|
170
|
+
swaggerUI({
|
|
171
|
+
url: '/openapi.json',
|
|
172
|
+
title: 'Swagger UI',
|
|
173
|
+
}),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
// ───────────────────────────────────────────────────────────────
|
|
177
|
+
// 6. Bun canonical entrypoint
|
|
178
|
+
// ───────────────────────────────────────────────────────────────
|
|
179
|
+
|
|
180
|
+
export default app
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## 3. `hono-openapi` API Reference
|
|
186
|
+
|
|
187
|
+
### Import paths
|
|
188
|
+
|
|
189
|
+
**There is only one import path.** `hono-openapi` exports everything from its root:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import {
|
|
193
|
+
describeRoute, // middleware to annotate a route with OpenAPI metadata
|
|
194
|
+
describeResponse, // attach response schemas directly to a handler
|
|
195
|
+
validator, // validation middleware (wraps @hono/standard-validator)
|
|
196
|
+
resolver, // wrap a Zod/Valibot/etc schema for OpenAPI responses
|
|
197
|
+
openAPIRouteHandler, // serve the generated OpenAPI JSON document
|
|
198
|
+
generateSpecs, // programmatically generate the spec (for build-time caching)
|
|
199
|
+
} from 'hono-openapi'
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Evidence** ([`src/index.ts`](https://github.com/rhinobase/hono-openapi/blob/10f45a66ede3764b5e6065805fb60fd5df090466/src/index.ts#L1-L9)):
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
export { generateSpecs, openAPIRouteHandler } from "./handler.js";
|
|
206
|
+
export {
|
|
207
|
+
describeResponse,
|
|
208
|
+
describeRoute,
|
|
209
|
+
loadVendor,
|
|
210
|
+
resolver,
|
|
211
|
+
validator,
|
|
212
|
+
} from "./middlewares.js";
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
> **No subpath exports** such as `hono-openapi/zod` or `hono-openapi/valibot`. The package uses Standard Schema and auto-detects the validator vendor.
|
|
216
|
+
|
|
217
|
+
### `describeRoute()` middleware
|
|
218
|
+
|
|
219
|
+
Attach OpenAPI metadata to any Hono route. Use `resolver()` for response body schemas.
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
app.get(
|
|
223
|
+
'/path',
|
|
224
|
+
describeRoute({
|
|
225
|
+
tags: ['Users'],
|
|
226
|
+
summary: 'Get user',
|
|
227
|
+
description: 'Retrieve a single user by ID',
|
|
228
|
+
responses: {
|
|
229
|
+
200: {
|
|
230
|
+
description: 'User found',
|
|
231
|
+
content: {
|
|
232
|
+
'application/json': {
|
|
233
|
+
schema: resolver(UserSchema),
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
404: {
|
|
238
|
+
description: 'User not found',
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
}),
|
|
242
|
+
handler,
|
|
243
|
+
)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Evidence** ([`src/middlewares.ts`](https://github.com/rhinobase/hono-openapi/blob/10f45a66ede3764b5e6065805fb60fd5df090466/src/middlewares.ts#L244-L254)):
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
export function describeRoute(spec: DescribeRouteOptions): MiddlewareHandler {
|
|
250
|
+
const middleware: MiddlewareHandler = async (_c, next) => {
|
|
251
|
+
await next();
|
|
252
|
+
};
|
|
253
|
+
return Object.assign(middleware, {
|
|
254
|
+
[uniqueSymbol]: { spec },
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### `validator()` middleware
|
|
260
|
+
|
|
261
|
+
Validates `query`, `json`, `param`, or `form` and **automatically** injects the request schema into the OpenAPI document. No manual `request` block in `describeRoute()` is required.
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
validator('query', QuerySchema) // ?name=foo
|
|
265
|
+
validator('json', JsonBodySchema) // POST body
|
|
266
|
+
validator('param', ParamSchema) // /users/:id
|
|
267
|
+
validator('form', FormSchema) // multipart/form-data
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Evidence** ([`src/middlewares.ts`](https://github.com/rhinobase/hono-openapi/blob/10f45a66ede3764b5e6065805fb60fd5df090466/src/middlewares.ts#L199-L237)):
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
export function validator<Schema extends StandardSchemaV1, ...>(
|
|
274
|
+
target: Target,
|
|
275
|
+
schema: Schema,
|
|
276
|
+
hook?: Hook<...>,
|
|
277
|
+
options?: ResolverReturnType["options"],
|
|
278
|
+
): MiddlewareHandler<E, P, V> {
|
|
279
|
+
const middleware = sValidator(target, schema, hook);
|
|
280
|
+
return Object.assign(middleware, {
|
|
281
|
+
[uniqueSymbol]: { target, ...resolver(schema, options), options },
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### `openAPIRouteHandler()` — serving the spec
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
app.get(
|
|
290
|
+
'/openapi.json',
|
|
291
|
+
openAPIRouteHandler(app, {
|
|
292
|
+
documentation: {
|
|
293
|
+
info: { title: 'Hono API', version: '1.0.0' },
|
|
294
|
+
servers: [{ url: 'http://localhost:3000' }],
|
|
295
|
+
},
|
|
296
|
+
}),
|
|
297
|
+
)
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Evidence** ([`src/handler.ts`](https://github.com/rhinobase/hono-openapi/blob/10f45a66ede3764b5e6065805fb60fd5df090466/src/handler.ts#L42-L59)):
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
export function openAPIRouteHandler<...>(
|
|
304
|
+
hono: Hono<E, S, P>,
|
|
305
|
+
options?: Partial<GenerateSpecOptions>,
|
|
306
|
+
): MiddlewareHandler<E, P, I> {
|
|
307
|
+
let specs: OpenAPIV3_1.Document;
|
|
308
|
+
return async (c) => {
|
|
309
|
+
if (specs) return c.json(specs);
|
|
310
|
+
specs = await generateSpecs(hono, options, c);
|
|
311
|
+
return c.json(specs);
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
> **Mount path convention**: `/openapi.json` is the most common. Some projects use `/openapi/spec.json` (e.g. [NamesMT/starter-monorepo](https://github.com/NamesMT/starter-monorepo/blob/main/apps/backend/src/openAPI.ts)).
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## 4. `@scalar/hono-api-reference` Setup
|
|
321
|
+
|
|
322
|
+
### Import path and package name
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import { Scalar } from '@scalar/hono-api-reference'
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
> **Deprecated**: `apiReference` is still exported but deprecated in favor of `Scalar` ([PR #5297](https://github.com/scalar/scalar/pull/5297)).
|
|
329
|
+
|
|
330
|
+
**Evidence** ([`integrations/hono/src/index.ts`](https://github.com/scalar/scalar/blob/8bcf8bf52a0da667d44eeec08648e3b1da044f97/integrations/hono/src/index.ts#L1-L9)):
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
import { Scalar } from './scalar'
|
|
334
|
+
export {
|
|
335
|
+
Scalar,
|
|
336
|
+
/**
|
|
337
|
+
* @deprecated Use `Scalar` instead.
|
|
338
|
+
*/
|
|
339
|
+
Scalar as apiReference,
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Mount path convention
|
|
344
|
+
|
|
345
|
+
Common choices:
|
|
346
|
+
- `/scalar` — matches the middleware name
|
|
347
|
+
- `/docs` — generic documentation endpoint
|
|
348
|
+
- `/openapi/ui` — nested under the OpenAPI prefix
|
|
349
|
+
|
|
350
|
+
### Configuration options
|
|
351
|
+
|
|
352
|
+
The Hono middleware accepts the **universal Scalar configuration** plus Hono-specific overrides (`pageTitle`, `cdn`).
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
app.get('/scalar', Scalar({
|
|
356
|
+
// ── Source (required) ──
|
|
357
|
+
url: '/openapi.json', // URL to the OpenAPI spec
|
|
358
|
+
|
|
359
|
+
// ── Appearance ──
|
|
360
|
+
theme: 'saturn', // 'alternate' | 'default' | 'moon' | 'purple'
|
|
361
|
+
// | 'solarized' | 'bluePlanet' | 'deepSpace'
|
|
362
|
+
// | 'saturn' | 'kepler' | 'elysiajs' | 'fastify'
|
|
363
|
+
// | 'mars' | 'laserwave' | 'none'
|
|
364
|
+
pageTitle: 'My API Docs', // HTML <title>
|
|
365
|
+
customCss: '.sidebar { ... }', // injected <style> block
|
|
366
|
+
metaData: { title: '...' }, // SEO meta tags (unhead format)
|
|
367
|
+
favicon: '/favicon.svg',
|
|
368
|
+
|
|
369
|
+
// ── Behavior ──
|
|
370
|
+
layout: 'modern', // 'modern' | 'classic'
|
|
371
|
+
darkMode: true,
|
|
372
|
+
forceDarkModeState: 'dark', // 'dark' | 'light'
|
|
373
|
+
hideDarkModeToggle: false,
|
|
374
|
+
hideModels: false,
|
|
375
|
+
hideSearch: false,
|
|
376
|
+
hideTestRequestButton: false,
|
|
377
|
+
showOperationId: false,
|
|
378
|
+
showSidebar: true,
|
|
379
|
+
|
|
380
|
+
// ── Proxy / Server ──
|
|
381
|
+
proxyUrl: 'https://proxy.scalar.com',
|
|
382
|
+
baseServerURL: 'http://localhost:3000',
|
|
383
|
+
servers: [{ url: 'http://localhost:3000' }],
|
|
384
|
+
|
|
385
|
+
// ── CDN ──
|
|
386
|
+
cdn: 'https://cdn.jsdelivr.net/npm/@scalar/api-reference',
|
|
387
|
+
|
|
388
|
+
// ── Advanced ──
|
|
389
|
+
authentication: { ... },
|
|
390
|
+
hiddenClients: ['unirest'],
|
|
391
|
+
defaultHttpClient: { targetKey: 'js', clientKey: 'fetch' },
|
|
392
|
+
plugins: [...],
|
|
393
|
+
pathRouting: { basePath: '/reference' },
|
|
394
|
+
mcp: { name: 'My MCP', url: '...' },
|
|
395
|
+
}))
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Evidence** — Scalar types define the full schema:
|
|
399
|
+
- [Base configuration (themes, proxy, etc.)](https://github.com/scalar/scalar/blob/8bcf8bf52a0da667d44eeec08648e3b1da044f97/packages/types/src/api-reference/base-configuration.ts#L110-L129)
|
|
400
|
+
- [HTML rendering configuration (`pageTitle`, `cdn`)](https://github.com/scalar/scalar/blob/8bcf8bf52a0da667d44eeec08648e3b1da044f97/packages/types/src/api-reference/html-rendering-configuration.ts#L8-L23)
|
|
401
|
+
- [Source configuration (`url`, `content`)](https://github.com/scalar/scalar/blob/8bcf8bf52a0da667d44eeec08648e3b1da044f97/packages/types/src/api-reference/source-configuration.ts#L8-L55)
|
|
402
|
+
- [Full API reference configuration](https://github.com/scalar/scalar/blob/8bcf8bf52a0da667d44eeec08648e3b1da044f97/packages/types/src/api-reference/api-reference-configuration.ts#L22-L379)
|
|
403
|
+
|
|
404
|
+
### Dynamic configuration (request-aware)
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
app.get('/scalar', Scalar((c) => ({
|
|
408
|
+
url: '/openapi.json',
|
|
409
|
+
proxyUrl: c.env.ENVIRONMENT === 'development'
|
|
410
|
+
? 'https://proxy.scalar.com'
|
|
411
|
+
: undefined,
|
|
412
|
+
})))
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
**Evidence** ([`integrations/hono/src/scalar.ts`](https://github.com/scalar/scalar/blob/8bcf8bf52a0da667d44eeec08648e3b1da044f97/integrations/hono/src/scalar.ts#L75-L94)):
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
export const Scalar = <E extends Env>(configOrResolver: Configuration<E>): MiddlewareHandler<E> => {
|
|
419
|
+
return async (c) => {
|
|
420
|
+
let resolvedConfig: Partial<ApiReferenceConfiguration> = {}
|
|
421
|
+
if (typeof configOrResolver === 'function') {
|
|
422
|
+
resolvedConfig = await configOrResolver(c)
|
|
423
|
+
} else {
|
|
424
|
+
resolvedConfig = configOrResolver
|
|
425
|
+
}
|
|
426
|
+
// ...
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## 5. `@hono/swagger-ui` Setup
|
|
434
|
+
|
|
435
|
+
### Import path and package name
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
import { swaggerUI } from '@hono/swagger-ui'
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**Evidence** ([`packages/swagger-ui/src/index.ts`](https://github.com/honojs/middleware/blob/eb443a2fbda674bbe12d3f30e96854bb0cad6232/packages/swagger-ui/src/index.ts#L93)):
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
export { middleware as swaggerUI, SwaggerUI }
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Mount path convention
|
|
448
|
+
|
|
449
|
+
Common choices:
|
|
450
|
+
- `/swagger` — explicit
|
|
451
|
+
- `/ui` — used in Hono official examples
|
|
452
|
+
- `/docs` — generic
|
|
453
|
+
|
|
454
|
+
### Configuration options
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
app.get('/swagger', swaggerUI({
|
|
458
|
+
url: '/openapi.json', // URL to the OpenAPI spec (required)
|
|
459
|
+
title: 'Swagger UI', // HTML page title
|
|
460
|
+
version: 'latest', // Swagger UI CDN version
|
|
461
|
+
// Any standard Swagger UI option also works:
|
|
462
|
+
// presets, plugins, urls, etc.
|
|
463
|
+
}))
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
**Evidence** ([`packages/swagger-ui/src/index.ts`](https://github.com/honojs/middleware/blob/eb443a2fbda674bbe12d3f30e96854bb0cad6232/packages/swagger-ui/src/index.ts#L8-L43)):
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
type SwaggerUIOptions = OriginalSwaggerUIOptions & DistSwaggerUIOptions
|
|
470
|
+
|
|
471
|
+
const middleware = <E extends Env>(options: SwaggerUIOptions): MiddlewareHandler<E> =>
|
|
472
|
+
async (c) => {
|
|
473
|
+
const title = options?.title ?? 'SwaggerUI'
|
|
474
|
+
return c.html(/* html */ `...`)
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## 6. Bun Runtime Entrypoint
|
|
481
|
+
|
|
482
|
+
### Canonical shape for `bun run`
|
|
483
|
+
|
|
484
|
+
```typescript
|
|
485
|
+
import { Hono } from 'hono'
|
|
486
|
+
|
|
487
|
+
const app = new Hono()
|
|
488
|
+
// ... routes ...
|
|
489
|
+
|
|
490
|
+
export default app
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
**Evidence** ([Hono Bun docs](https://hono.dev/docs/getting-started/bun)):
|
|
494
|
+
|
|
495
|
+
> ```ts
|
|
496
|
+
> import { Hono } from 'hono'
|
|
497
|
+
> const app = new Hono()
|
|
498
|
+
> app.get('/', (c) => c.text('Hello Bun!'))
|
|
499
|
+
> export default app
|
|
500
|
+
> ```
|
|
501
|
+
|
|
502
|
+
### Custom port
|
|
503
|
+
|
|
504
|
+
```typescript
|
|
505
|
+
export default {
|
|
506
|
+
port: 3000,
|
|
507
|
+
fetch: app.fetch,
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
**Evidence** ([Hono Bun docs — Change port number](https://hono.dev/docs/getting-started/bun)):
|
|
512
|
+
|
|
513
|
+
> ```ts
|
|
514
|
+
> export default {
|
|
515
|
+
> port: 3000,
|
|
516
|
+
> fetch: app.fetch,
|
|
517
|
+
> }
|
|
518
|
+
> ```
|
|
519
|
+
|
|
520
|
+
### `package.json` scripts for Bun
|
|
521
|
+
|
|
522
|
+
```json
|
|
523
|
+
{
|
|
524
|
+
"scripts": {
|
|
525
|
+
"dev": "bun run --hot src/index.ts",
|
|
526
|
+
"start": "bun run src/index.ts",
|
|
527
|
+
"build": "tsc --noEmit"
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## 7. OpenAPI Version
|
|
535
|
+
|
|
536
|
+
### `hono-openapi` emits **OpenAPI 3.1.0** by default
|
|
537
|
+
|
|
538
|
+
This is **hardcoded** in the source and **not configurable** at runtime:
|
|
539
|
+
|
|
540
|
+
**Evidence** ([`src/handler.ts` line 120](https://github.com/rhinobase/hono-openapi/blob/10f45a66ede3764b5e6065805fb60fd5df090466/src/handler.ts#L120)):
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
return {
|
|
544
|
+
openapi: "3.1.0",
|
|
545
|
+
..._documentation,
|
|
546
|
+
// ...
|
|
547
|
+
} satisfies OpenAPIV3_1.Document;
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
> If you need OpenAPI 3.0.x, you must post-process the generated spec or use `@hono/zod-openapi` (the older package) instead. The user explicitly requested `hono-openapi`, so document that 3.1.0 is the only output.
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## 8. Zod v3 vs Zod v4
|
|
555
|
+
|
|
556
|
+
| Feature | Zod v3 | Zod v4 |
|
|
557
|
+
|---------|--------|--------|
|
|
558
|
+
| Standard Schema | ❌ No | ✅ Yes (native) |
|
|
559
|
+
| `hono-openapi` extra deps | `zod-openapi@4` | None |
|
|
560
|
+
| Import path | `import { z } from 'zod'` | `import { z } from 'zod'` (or `zod/v4` for explicit) |
|
|
561
|
+
|
|
562
|
+
**For Zod v3 users**, install the compatibility layer:
|
|
563
|
+
|
|
564
|
+
```bash
|
|
565
|
+
npm install zod-openapi@4
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Then use `zod-openapi`'s `.openapi()` for metadata and `.meta({ ref: 'Name' })` for component references. `hono-openapi`'s `resolver()` will still work, but the underlying schema conversion relies on `zod-openapi@4`.
|
|
569
|
+
|
|
570
|
+
**Evidence** ([HonoHub Zod docs](https://honohub.dev/docs/openapi/zod)):
|
|
571
|
+
|
|
572
|
+
> "For zod v3, you can use the `zod-openapi` library. You need to install `zod-openapi@4` for this to work properly."
|
|
573
|
+
|
|
574
|
+
**For Zod v4 users** (recommended in 2026), no extra packages are needed. `z.date()` is automatically converted to `{ type: 'string', format: 'date-time' }`.
|
|
575
|
+
|
|
576
|
+
**Evidence** ([`src/middlewares.ts` Zod v4 date override](https://github.com/rhinobase/hono-openapi/blob/10f45a66ede3764b5e6065805fb60fd5df090466/src/middlewares.ts#L63-L71)):
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
const zodV4DateOverride = (ctx: { ... }) => {
|
|
580
|
+
if (ctx.zodSchema._zod.def.type === "date") {
|
|
581
|
+
ctx.jsonSchema.type = "string";
|
|
582
|
+
ctx.jsonSchema.format = "date-time";
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
## 9. Real-World Example
|
|
590
|
+
|
|
591
|
+
**NamesMT/starter-monorepo** — a public monorepo starter using `hono-openapi` + `@scalar/hono-api-reference` together:
|
|
592
|
+
|
|
593
|
+
- File: [`apps/backend/src/openAPI.ts`](https://github.com/NamesMT/starter-monorepo/blob/main/apps/backend/src/openAPI.ts)
|
|
594
|
+
- Pattern: mounts spec at `/openapi/spec.json` and Scalar UI at `/openapi/ui`
|
|
595
|
+
|
|
596
|
+
```typescript
|
|
597
|
+
import type { Hono } from 'hono'
|
|
598
|
+
import { Scalar } from '@scalar/hono-api-reference'
|
|
599
|
+
import { openAPIRouteHandler } from 'hono-openapi'
|
|
600
|
+
|
|
601
|
+
export function setupOpenAPI(app: Hono<any, any>, prefix = '/openapi') {
|
|
602
|
+
app.get(
|
|
603
|
+
`${prefix}/spec.json`,
|
|
604
|
+
openAPIRouteHandler(app, {
|
|
605
|
+
documentation: {
|
|
606
|
+
info: {
|
|
607
|
+
title: `starter-monorepo's backend`,
|
|
608
|
+
version: '1.0.0',
|
|
609
|
+
description: 'My amazing API',
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
}),
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
app.get(
|
|
616
|
+
`${prefix}/ui`,
|
|
617
|
+
Scalar({
|
|
618
|
+
theme: 'deepSpace',
|
|
619
|
+
url: `${prefix}/spec.json`,
|
|
620
|
+
}),
|
|
621
|
+
)
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
> **Note**: No public repo was found using all four (`hono-openapi` + `Scalar` + `swagger-ui` + `hono`) in a single file. The canonical combination in the wild is `hono-openapi` + `Scalar`. Adding `swagger-ui` is a trivial parallel mount (shown in the `app.ts` above).
|
|
626
|
+
|
|
627
|
+
---
|
|
628
|
+
|
|
629
|
+
## 10. Common Pitfalls
|
|
630
|
+
|
|
631
|
+
1. **Using `openAPISpecs` instead of `openAPIRouteHandler`**
|
|
632
|
+
Some docs (e.g. HONC) use `openAPISpecs` — this is **not** the current export name. The correct function is `openAPIRouteHandler` ([source](https://github.com/rhinobase/hono-openapi/blob/10f45a66ede3764b5e6065805fb60fd5df090466/src/index.ts#L1)).
|
|
633
|
+
|
|
634
|
+
2. **Importing from `hono-openapi/zod`**
|
|
635
|
+
There are **no subpath exports**. Always import from `hono-openapi` directly.
|
|
636
|
+
|
|
637
|
+
3. **Forgetting `@hono/standard-validator`**
|
|
638
|
+
It is a peer dependency of `hono-openapi`. Modern package managers (npm ≥ 7, pnpm, bun) auto-install it. If you see validation errors, ensure it is present in `node_modules`.
|
|
639
|
+
|
|
640
|
+
4. **Using `@hono/zod-openapi` (the OLD package)**
|
|
641
|
+
The user explicitly wants `hono-openapi` (the newer, middleware-based, Standard Schema package). Do not confuse with `@hono/zod-openapi` which wraps the `Hono` class into `OpenAPIHono`.
|
|
642
|
+
|
|
643
|
+
5. **Swagger UI `spec` option**
|
|
644
|
+
`@hono/swagger-ui` does **not** accept a `spec` option to embed the document directly. It only accepts `url` (or `urls`) pointing to an external spec endpoint. If you need embedded specs, use Scalar's `content` option instead.
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## 11. Quick Start Commands
|
|
649
|
+
|
|
650
|
+
```bash
|
|
651
|
+
# 1. Create project
|
|
652
|
+
mkdir my-api && cd my-api
|
|
653
|
+
bun init -y
|
|
654
|
+
|
|
655
|
+
# 2. Install dependencies
|
|
656
|
+
bun add hono hono-openapi @scalar/hono-api-reference @hono/swagger-ui zod
|
|
657
|
+
|
|
658
|
+
# 3. Add TypeScript
|
|
659
|
+
bun add -d typescript @types/bun
|
|
660
|
+
|
|
661
|
+
# 4. Write app.ts (copy from section 2 above)
|
|
662
|
+
# 5. Run
|
|
663
|
+
bun run --hot app.ts
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
Endpoints after startup:
|
|
667
|
+
- `GET /health` — health check
|
|
668
|
+
- `GET /hello?name=world` — documented route
|
|
669
|
+
- `POST /users` — validated JSON body route
|
|
670
|
+
- `GET /openapi.json` — raw OpenAPI 3.1.0 spec
|
|
671
|
+
- `GET /scalar` — Scalar API Reference UI
|
|
672
|
+
- `GET /swagger` — Swagger UI
|