@fastify/swagger-ui
Serves an interactive Swagger UI inside a Fastify app, rendered directly from the OpenAPI spec that @fastify/swagger already generates.
Repository Health
Technical Analysis
@fastify/swagger-ui is the official Fastify plugin that turns the OpenAPI document produced by @fastify/swagger into a browsable, interactive documentation page. Registering it adds a /documentation route (configurable) that serves the bundled Swagger UI assets, exposes the spec as both JSON and YAML, and lets every route’s try it out calls hit the live API directly from the browser.
Beyond the default setup, the plugin covers the practical concerns real deployments run into: a staticCSP option that generates or lets you transform a content-security-policy header for the served assets, uiHooks so the documentation routes can sit behind the same onRequest/preHandler auth hooks as the rest of the app, a theme option for injecting custom CSS/JS/favicon and swapping the logo, and a transformSpecification hook for mutating the spec per-request (for example rewriting the host based on the incoming request). A baseDir option additionally supports bundling the UI’s static files alongside the app for environments where the package can’t be resolved from node_modules at runtime.
What You Get
- A configurable documentation route (default
/documentation) serving the bundled Swagger UI, plus/documentation/jsonand/documentation/yamlendpoints for the raw spec - A
staticCSPoption that auto-generates a content-security-policy header for the UI’s static assets, or atransformStaticCSPhook to modify one already set uiHookssupport so the documentation routes can be protected by the sameonRequest/preHandlerhooks used elsewhere in the app (e.g.@fastify/basic-auth)- A
themeoption to inject custom CSS/JS/favicon files and override the Swagger UI logo, title, and OAuth init config - A
transformSpecificationhook to mutate the served spec per-request (host rewriting, environment-specific server lists, response caching via a disabled auto-clone) - A
baseDiroption to bundle the Swagger UI static files with the app for esbuild/Docker deployments wherenode_modulesresolution isn’t available at runtime
Common Use Cases
- Exposing interactive, try-it-out API documentation for a Fastify service without hand-writing an HTML/JS docs page
- Gating internal or partner API docs behind existing Fastify auth hooks via
uiHooks - Serving environment-aware specs (e.g. rewriting
host/server URLs per request) behind a CDN or reverse proxy - White-labeling the documentation UI with a custom logo, theme CSS/JS, and favicon for a product’s branding
- Bundling the UI’s static assets into a container image or serverless bundle via
baseDirwhen the package itself isn’t deployed tonode_modules
Under The Hood
Architecture
The plugin is a single fastify-plugin-wrapped function (index.js) that declares a hard dependency on @fastify/swagger via the dependencies option passed to fastify-plugin, so Fastify itself enforces registration order. The real work happens in lib/routes.js, which registers a flat set of routes (the index page, /json, /yaml, theme asset routes, and a catch-all for baseDir-based external $ref files) directly against the Fastify instance, builds an optional content-security-policy header from a swaggerCSP decorator computed at plugin registration, and serves the actual Swagger UI static bundle through @fastify/static. Request-scoped behavior (spec transformation, cloning via rfdc, CSP header mutation) is resolved into pre-selected handler functions at registration time rather than branched on every request, keeping the hot path free of repeated option checks.
Tech Stack
Built on Fastify 5.x’s plugin system, with @fastify/static for serving the bundled UI assets, fastify-plugin for encapsulation-safe registration, yaml for the /yaml spec endpoint, openapi-types for typing the OpenAPI document, and rfdc for fast deep-cloning the spec before user-supplied transform functions run. The actual Swagger UI distribution (swagger-ui-dist) is vendored into the package’s static/ directory at publish time via a prepare script rather than pulled in as a runtime dependency.
Code Quality
The test suite (node --test under c8) enforces 100% coverage (c8 --100) across CSP handling, hooks, theming, static file serving, spec transformation, and the swagger-initializer template, backed by a separate Playwright e2e suite that exercises the served UI in a real browser. Types are hand-written in types/index.d.ts and verified with tstyche type tests rather than left unchecked. Linting runs through neostandard (ESLint) with a dedicated CI job, and the CI pipeline branches into a required Playwright e2e job before the shared Fastify org test/lint/license-check workflow runs.
API Design
The plugin exposes a single registration call with one options object, mirroring the rest of the Fastify plugin ecosystem, so there’s no additional API surface to learn beyond configuring routePrefix, uiConfig, uiHooks, theme, and the transform hooks. Options compose cleanly with @fastify/swagger’s own configuration and with unrelated hook-based plugins (auth, CSP), which keeps the barrier to a working documentation page low even for teams new to Fastify’s plugin model.
Used by 6 apps in this directory
Dittofeed
Marketing · Automation
Open-source omni-channel customer engagement platform for automating transactional and marketing messages via email, SMS, WhatsApp, Slack, and mobile push.
Infisical
Security · Devops
The open-source platform for secrets, certificates, privileged access, and AI agent security — all in one self-hostable system.
Mastra Code
AI Code Assistants
"A coding agent that never compacts" — a terminal-based AI coding agent built on the Mastra framework, with Observational Memory instead of context compaction, multi-model support, and OAuth login for Claude Max or ChatGPT Plus.
OpenPanel
Analytics
Open-source Mixpanel alternative with session replay, MCP integration, and privacy-first product analytics you fully control.
optio
AI Agents · AI Code Assistants
Self-hosted AI agent workflow orchestration that runs on your Kubernetes cluster — from ticket intake to squash-merged PR, entirely within your infrastructure.
Palmr.
File Storage · Security
Self-hosted, privacy-focused file sharing without limits