Configuration
All adapters accept the same config object.
{
docsPath: '/docs', // URL where the docs UI is served
enabled: true, // Set false to disable; defaults to NODE_ENV !== 'production'
liveReload: false, // Re-discover routes on every docs hit
meta: {
title: 'My API',
version: '1.0.0',
description: 'Full description shown in the UI header',
},
exclude: ['/health', /^\/internal\/.*/], // Paths to hide from docs
groups: { // Group routes under named sections in the sidebar
Users: ['/users', '/users/:id'],
Products: '/products',
},
flows: [...], // Inline flow presets (see Request Flows)
flowsPath: './doctreen-flows', // Directory of *.json flow files
}Reference
| Option | Type | Default | Description |
|---|---|---|---|
docsPath | string | '/docs' | URL where the docs UI is served |
enabled | boolean | NODE_ENV !== 'production' | Set to false to disable docs entirely |
liveReload | boolean | false | Re-discover routes on every docs request |
meta.title | string | 'API Documentation' | Title shown in the UI header |
meta.version | string | '1.0.0' | Version label |
meta.description | string | '' | Description shown below the title |
exclude | string | RegExp | Array | [] | Routes to hide from the docs |
groups | Record<string, string | string[]> | {} | Group routes into named sidebar sections |
flows | FlowDefinition[] | null | Inline request-flow presets |
flowsPath | string | auto-detected | Directory of *.json flow files |
validate | boolean | ValidateConfig | false | Run runtime validation on every Zod-declared route |
defaultErrors | Record<number, string | { description?, schema? }> | {} | Default error responses merged into every route (v1.15+) |
drift | boolean | DriftConfig | env-dependent | Enable schema drift detection |
openapi | OpenAPIConfig | {} | Tags, servers, security schemes, callbacks/webhooks for the OpenAPI export |
headHtml | string | '' | Inject custom <head> HTML (analytics, favicons, OG tags) |
Disabling in production
By default enabled is false when NODE_ENV === 'production'. To serve docs
in production, set it explicitly:
expressAdapter(app, { enabled: true, meta: { title: 'My API', version: '1.0.0' } });Excluding routes
exclude accepts strings, regexes, or arrays of either:
expressAdapter(app, {
exclude: [
'/health',
'/metrics',
/^\/internal\/.*/,
],
});For per-route control while keeping the route reachable, use
hidden: true on
defineRoute / @DocRoute instead.
Validation options v1.15
validate accepts a boolean or an object for finer control:
validate: boolean | {
enabled?: boolean; // Run validation (default when object form is used)
writeback?: boolean; // Write the parsed payload back onto the request
response?: 'off' | 'warn' | 'throw'; // Dev-mode response assertion (default 'off')
}validate: trueis shorthand for{ enabled: true }— validate the request, but don't mutate it (legacy behavior).writeback: truewrites the parsed (coerced and defaulted) payload back onto the request, so your handler sees the cleaned values.response: 'warn' | 'throw'asserts handler responses against their declared schema in development.
See runtime validation for the full behavior.
Default error responses v1.15
defaultErrors declares error responses applied to every route, keyed by HTTP
status — the same shape as a route's errors. It
kills the boilerplate of repeating 401 / 403 / 422 on every
defineRoute. Each route's own errors win on a status conflict.
expressAdapter(app, {
defaultErrors: {
401: 'Authentication required',
403: 'Forbidden',
422: { description: 'Validation failed', schema: s.object({ error: s.string() }) },
},
});