Interactive Docs UI
Stratal serves an interactive API reference directly from your worker using Swagger UI by default. The UI reads the generated OpenAPI spec and renders a browsable, searchable interface where consumers can explore endpoints, view schemas, and try out requests.
The renderer is pluggable — you can swap Swagger UI for any renderer that returns a Hono middleware handler.
Accessing the docs
Section titled “Accessing the docs”Once the OpenAPIModule is registered, the interactive docs are available at the configured UI path. With default settings, start your dev server and visit:
http://localhost:8787/api/docsThe JSON spec that powers the UI is available at:
http://localhost:8787/api/openapi.jsonYou can import this URL into external tools like Postman, Insomnia, or any OpenAPI-compatible client.
Customizing the docs path
Section titled “Customizing the docs path”Change where the UI is served by passing the ui option to forRoot():
OpenAPIModule.forRoot({ info: { title: 'My API', version: '2.0.0' }, ui: { path: '/docs' }, jsonPath: '/openapi.json',})With this configuration:
- Interactive docs are at
/docs - JSON spec is at
/openapi.json
Using a custom renderer
Section titled “Using a custom renderer”The ui.renderer option accepts a function that receives an OpenAPIUIContext and returns a Hono middleware handler. This lets you replace Swagger UI with any documentation renderer.
The OpenAPIUIRenderer type is defined as:
import type { MiddlewareHandler } from 'hono'
interface OpenAPIUIContext { specUrl: string title: string}
type OpenAPIUIRenderer = (context: OpenAPIUIContext) => MiddlewareHandlerHere is an example using a custom renderer:
import type { OpenAPIUIRenderer } from 'stratal/openapi'
const myRenderer: OpenAPIUIRenderer = ({ specUrl, title }) => { return (c) => { const html = ` <!DOCTYPE html> <html> <head><title>${title}</title></head> <body> <h1>${title}</h1> <p>Spec available at <a href="${specUrl}">${specUrl}</a></p> </body> </html> ` return c.html(html) }}
OpenAPIModule.forRoot({ info: { title: 'My API', version: '1.0.0' }, ui: { renderer: myRenderer },})Disabling the UI
Section titled “Disabling the UI”Set ui to false to disable the interactive docs entirely:
OpenAPIModule.forRoot({ info: { title: 'My API', version: '1.0.0' }, ui: false,})Runtime overrides
Section titled “Runtime overrides”The OpenAPIConfigService is request-scoped, which means you can change the docs title or apply route filters on a per-request basis. This is useful when you want to customize the documentation per environment or API version.
Here is a middleware that overrides the spec title based on a request header:
import { inject } from 'stratal/di'import { Middleware, MiddlewareHandler } from 'stratal/middleware'import { RouterContext } from 'stratal/router'import { OPENAPI_TOKENS } from 'stratal/openapi'import type { IOpenAPIConfigService } from 'stratal/openapi'
@Middleware()export class EnvironmentDocsMiddleware implements MiddlewareHandler { constructor( @inject(OPENAPI_TOKENS.ConfigService) private openApiConfig: IOpenAPIConfigService, ) {}
async handle(ctx: RouterContext, next: () => Promise<void>) { const environment = ctx.header('X-Environment') ?? 'production'
this.openApiConfig.override({ info: { title: `My API (${environment})`, description: `API documentation for the ${environment} environment`, }, })
await next() }}Each request gets its own instance of OpenAPIConfigService, so overrides in one request do not affect others. The override is merged with the base configuration: any fields you set replace the base values, and any fields you omit keep their defaults.
Next steps
Section titled “Next steps”You now have a complete picture of Stratal’s OpenAPI system. From here you can explore:
- Controllers and Routing for more on how controllers work beyond the OpenAPI conventions.
- Guards for protecting routes with authentication and authorization.
- Middleware for request processing pipelines.