DocfyUiModule.setup(mountPath, app, options?)

Serves docfy-ui (this package's AI-first companion documentation UI) at mountPath, the same role that SwaggerModule.setup() + swagger-ui-express play for the raw Swagger UI.

Usage

Works on both Express (@nestjs/platform-express) and Fastify (@nestjs/platform-fastify) apps. On Fastify, static asset serving needs the optional peer dependency @fastify/static (npm install @fastify/static), the same package @nestjs/swagger itself relies on for Fastify Swagger UI support.

ts
import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { DocfyUiModule } from 'nestjs-docfy';

const app = await NestFactory.create(AppModule);

DocfyUiModule.setup('/docs', app); // before SwaggerModule.setup; see staticSpecPath below

const document = SwaggerModule.createDocument(app, new DocumentBuilder().build());
SwaggerModule.setup('api', app, document); // exposes /api-json, which docfy-ui fetches by default

await app.listen(3000);

Visit /docs: no further configuration is needed, since docfy-ui fetches /api-json same-origin by default.

Options

OptionTypeDefaultDescription
staticSpecPathstringnonePath to a pre-built OpenAPI JSON file, served at /api-json instead of the app's live one.
specs{ name: string; url: string }[]noneExtra OpenAPI specs to offer in docfy-ui's spec switcher, so one deployed instance can browse more than one service's documentation.
openApiDocument{ servers?: { url: string }[] }noneEnables the "Try it out" same-origin proxy — pass the same object you already have from SwaggerModule.createDocument(). See below.
additionalProxyOriginsstring[]noneExtra origins the proxy is allowed to forward requests to, beyond what openApiDocument.servers declares.
guides{ slug, title, content }[]noneNarrative markdown pages at /guides/:slug, listed in the sidebar. A guide can embed a live, runnable request via a docfy-try fenced block (single line METHOD /path matching an endpoint in the current spec) — renders the endpoint's real request panel inline instead of just linking to its page.

staticSpecPath (needed under webpack: true, if you're not using the CLI plugin)

The DocfyModule runtime metadata pipeline can't apply docs files there, so the live /api-json will be missing everything docs files would add. See The CLI plugin for the recommended, automatic fix. This section covers the manual alternative: generate a patched document beforehand:

bash
npx nestjs-docfy patch-spec --spec http://localhost:3000/api-json --out openapi.patched.json

And serve it:

ts
DocfyUiModule.setup('/docs', app, { staticSpecPath: './openapi.patched.json' });

Call this before SwaggerModule.setup(): Express resolves routes in registration order, so the patched static document takes precedence over the live one for any request to /api-json. On Fastify, SwaggerModule.setup() registering its own /api-json route alongside this throws FST_ERR_DUPLICATED_ROUTE at startup instead. Registration order doesn't help there, so point SwaggerModule.setup() at a different jsonDocumentUrl (or pass { raw: false }) when combining it with staticSpecPath on Fastify.

Same-origin proxy

Enables docfy-ui's "Try it out" same-origin proxy. Without it, request execution does a direct fetch from the browser to the target API, subject to that API's own CORS policy. With it, this module registers a same-origin route () and the browser calls that instead: the proxy makes the real request server-to-server, so CORS never applies. Pass the same document you already have from SwaggerModule.createDocument():

ts
const document = SwaggerModule.createDocument(app, new DocumentBuilder().build());
SwaggerModule.setup('api', app, document);
DocfyUiModule.setup('/docs', app, { openApiDocument: document });

The proxy's allowlist is built only from absolute URLs in the document's servers[] array, plus anything in additionalProxyOrigins. There's deliberately no implicit "same origin as this request" fallback, since that would have to be derived from a client-controlled Host header, a classic SSRF vector. A request for any other origin is rejected with and an response header.

Every other proxy-level failure (target unreachable, timeout, malformed request) also sets , so docfy-ui can tell a proxy failure apart from a real 4xx/5xx response coming from your API. Those pass through untouched, with their real status/headers/body.