api-documentation-sync
API Documentation Sync
Two modes: Generate (routes → spec) or Validate (spec ↔ routes). Identify which mode applies before proceeding.
Phase 1: Discovery
Route extraction — non-obvious patterns to catch
Most routes are not just app.get(...). Scan for:
- Router mounts:
app.use('/prefix', router)— the prefix compounds. Reconstruct full paths. - Dynamic registrations: routes registered in loops, from config arrays, or via decorators — trace the source data.
- Middleware-as-route: auth middleware on
router.use(...)that also terminates requests (e.g., returns 401) — these are implicit endpoints. - Nested routers: routers mounted on routers. Build a full prefix chain.
- Framework-specific: NestJS
@Controller+@Get/@Postdecorators; FastAPIAPIRouter; Djangourlpatternswithinclude(); Hono.route().
Collect for each route:
- Full path (with all prefix segments resolved)
- HTTP method(s)
- Handler function name/location
- Any inline validation schema (Zod, Pydantic, Joi, Yup, class-validator)
- Auth guard presence (middleware name, decorator)
Schema extraction — non-obvious sources
Don't just look at request body. Extract:
- Path params: named captures in route strings (
:id,{id},<int:pk>) - Query params:
req.query.*accesses or framework query decorators - Response shapes: infer from
res.json(...)calls or explicit return type annotations - Validation schemas: Zod
.parse()/.safeParse(), Pydantic model in function signature, Joi.validate()— these are ground truth for request shape - Error responses: catch blocks that
res.status(4xx).json(...)— document these as response variants
Phase 2: Strategy
Generate mode
- Confirm OpenAPI version target (default: 3.1.0 unless codebase shows 3.0.x or Swagger 2.0)
- Determine output format: YAML (preferred for readability) or JSON
- Ask if existing partial spec exists to merge into — don't overwrite human-authored descriptions
- Identify reusable schemas (same shape used across multiple routes →
$reftocomponents/schemas)
Validate mode
- Parse the existing spec — note the
servers[].urlbase path, it affects path matching - Extract all
pathsentries from spec - Cross-reference against discovered routes using normalized path comparison:
- OpenAPI uses
{param}notation; Express uses:param— normalize before comparing - Ignore trailing slashes unless the framework distinguishes them
- OpenAPI uses
- Classify findings into three buckets:
- Ghost routes: in spec, not in code (deleted or renamed)
- Undocumented routes: in code, not in spec
- Drift: route exists in both but method, params, or response schema diverge
Phase 3: Execution
Generating the spec
Build the spec incrementally:
openapi: 3.1.0
info:
title: <infer from package.json name or ask>
version: <infer from package.json version or "0.1.0">
paths:
/resource/{id}:
get:
summary: <derive from handler name, e.g. getUserById → "Get user by ID">
parameters:
- name: id
in: path
required: true
schema:
type: string # or integer — infer from validation schema or usage
responses:
"200":
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/User'
"404":
description: Not found
Non-obvious generation rules:
- Handler name →
operationId: camelCase handler name maps directly.getUserById→operationId: getUserById - Auth middleware presence → add
securityfield on that operation (useBearerAuthas default scheme name) - If validation schema exists (Zod/Pydantic/Joi), derive the JSON Schema directly from it — don't guess
- For routes with no response type info, use
description: Successwith no schema rather than fabricating a shape - Group routes under shared tags by their first path segment (
/users/*→ tag:users)
Validating the spec
Output a structured diff report:
GHOST ROUTES (in spec, not in code):
DELETE /api/v1/users/{id} — handler not found
UNDOCUMENTED ROUTES (in code, not in spec):
POST /api/v1/auth/refresh
GET /api/v1/admin/stats
DRIFT DETECTED:
GET /api/v1/users/{id}
spec: response 200 → schema $ref User
code: handler returns { user, meta } — schema mismatch
POST /api/v1/orders
spec: body requires { productId, quantity }
code: Zod schema requires { productId, quantity, shippingAddressId }
For each drift item, suggest the fix (update spec or update code) based on which is more likely to be ground truth.
Phase 4: Output
Generate mode output
- Single
openapi.yaml(or.json) at project root ordocs/— ask if no convention is visible - If a partial spec existed, merge: preserve existing
description,summary,examplefields; updateparameters,requestBody,responsesfrom code
Validate mode output
- Report in the format above, grouped by severity
- Offer to: (a) auto-add undocumented routes to spec as stubs, (b) remove ghost routes, (c) flag drift items for manual review
- Never silently mutate the spec — always confirm before writing
Edge cases to handle
- Versioned APIs (
/v1/,/v2/): treat as separate tag groups, not separate specs unless user requests it - File upload routes:
multipart/form-datacontent type — set explicitly, notapplication/json - Streaming endpoints (SSE, chunked): note in spec as
text/event-stream, flag that schema coverage is limited - Health/internal routes (
/health,/metrics,/__internal): ask if these should be excluded from public spec - Optional auth: some routes accept both authenticated and unauthenticated requests with different responses — document both response variants
More from blunotech-dev/agents
anti-purple-ui
Enforce a strict monochrome UI with a single high-contrast accent color, removing generic tech gradients and “AI-style” palettes. Use when the user wants minimal, anti-AI, or non-generic aesthetics, or says the UI looks too techy or generic.
9harmonize-whitespace
Align all spacing (padding, margins, gaps) to a consistent 4pt/8pt grid. Use when spacing feels off, inconsistent, cramped, or unbalanced, or when the user asks for a spacing scale or alignment fix.
9typographic-hierarchy
Improve typography by adjusting font sizes, weights, spacing, and contrast to create clear visual hierarchy and readability. Use when text feels flat, unstructured, or when the user asks to refine headings, type scale, or overall readability.
6micro-interaction-adder
Add polished CSS micro-interactions like hover effects, transitions, and feedback states to improve UI feel. Use when the user asks for animations, better UX, or when the interface feels static, plain, or unresponsive.
4consistent-border-radius
Normalizes rounded corners across a file so buttons, inputs, cards, modals, badges, and all UI elements share the exact same curvature. Use this skill whenever the user mentions inconsistent border radii, wants to unify rounded corners, asks to make UI elements look more cohesive, or says things like "make the corners match", "fix the rounding", "unify border radius", "standardize my rounded corners", or "buttons and cards don't match". Also trigger when the user pastes a CSS/HTML/JSX/TSX file and asks for a design consistency pass, border radius is one of the first things to normalize.
4component-split
Analyze a component and determine when and how to split it based on size, responsibility, and reuse signals, producing a refactored structure with clear boundaries. Use when users share large, mixed-concern, or hard-to-test components, or ask about splitting, refactoring, or improving component architecture.
3