Serving
Serve the OpenAPI spec at runtime with OpenApiModule
While nestjs-openapi generates specs statically, you can serve the generated specification at runtime using the included OpenApiModule.
Basic Usage
import { Module } from '@nestjs/common';
import { OpenApiModule } from 'nestjs-openapi';
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
}),
],
})
export class AppModule {}This serves the OpenAPI spec at GET /openapi.json.
Configuration Options
OpenApiModule.forRoot({
// Path to the generated OpenAPI JSON file (required)
specFile: 'openapi.json',
// Enable/disable the module (default: true)
enabled: process.env.NODE_ENV !== 'production',
// Path to serve the JSON spec (default: '/openapi.json')
jsonPath: '/openapi.json',
// Enable Swagger UI (default: false)
swagger: true,
// Or with custom options:
swagger: {
path: '/api-docs',
title: 'My API Documentation',
},
});Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
specFile | string | - | Path to the generated OpenAPI JSON file (required) |
enabled | boolean | true | Whether the module is enabled |
jsonPath | string | '/openapi.json' | Path to serve the JSON spec |
swagger | boolean | SwaggerOptions | false | Swagger UI configuration |
SwaggerOptions
| Option | Type | Default | Description |
|---|---|---|---|
path | string | '/api-docs' | Path for Swagger UI |
title | string | spec.info.title | Custom title for Swagger UI page |
With Swagger UI
Serve interactive documentation with Swagger UI:
// Simple: enable with defaults
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
swagger: true,
}),
],
})
export class AppModule {}
// Custom: configure path and title
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
swagger: {
path: '/docs',
title: 'My API Docs',
},
}),
],
})
export class AppModule {}This creates two endpoints:
GET /openapi.json- Raw OpenAPI specGET /docs- Swagger UI interface
Swagger UI is loaded from unpkg.com CDN. No additional packages are required.
Environment-Based Configuration
Disable in production or enable based on environment:
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
enabled: process.env.NODE_ENV !== 'production',
swagger: process.env.SWAGGER_UI === 'true',
}),
],
})
export class AppModule {}When enabled is false, no routes are registered and the module is essentially a no-op.
Custom Paths
Configure custom paths for both endpoints:
@Module({
imports: [
OpenApiModule.forRoot({
specFile: 'openapi.json',
jsonPath: '/api/v1/openapi.json',
swagger: {
path: '/api/v1/docs',
},
}),
],
})
export class AppModule {}File Path Resolution
The specFile is resolved relative to the current working directory (process.cwd()):
// Relative path (recommended)
specFile: 'openapi.json';
// Relative path with directory
specFile: 'src/openapi/spec.json';
// Absolute path
specFile: '/var/app/openapi.json';The spec file must exist when the NestJS application starts. Run
nestjs-openapi generate before starting your app.
Error Handling
If the spec file is not found, a helpful error is thrown:
OpenAPI spec file not found: openapi.json.
Make sure to run 'nestjs-openapi generate' first.Injecting the Spec
You can inject the loaded spec in your services:
import { Injectable, Inject } from '@nestjs/common';
import { OPENAPI_SPEC } from 'nestjs-openapi';
import type { OpenApiSpec } from 'nestjs-openapi';
@Injectable()
export class ApiInfoService {
constructor(@Inject(OPENAPI_SPEC) private readonly spec: OpenApiSpec) {}
getApiVersion(): string {
return this.spec.info.version;
}
getOperationCount(): number {
return Object.values(this.spec.paths).flatMap((methods) =>
Object.keys(methods),
).length;
}
}Available injection tokens:
OPENAPI_SPEC- The loaded OpenAPI specification objectOPENAPI_MODULE_OPTIONS- The resolved module options
Complete Example
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { OpenApiModule } from 'nestjs-openapi';
@Module({
imports: [
ConfigModule.forRoot(),
OpenApiModule.forRoot({
specFile: 'openapi.json',
enabled: process.env.NODE_ENV !== 'production',
jsonPath: '/api/openapi.json',
swagger: {
path: '/api/docs',
title: 'My API - Interactive Documentation',
},
}),
],
})
export class AppModule {}Workflow
The recommended workflow is:
-
Generate the spec during build/CI:
npm run build npx nestjs-openapi generate -c openapi.config.ts -
Commit the generated spec (optional but recommended)
-
Serve at runtime:
OpenApiModule.forRoot({ specFile: 'openapi.json', swagger: true, });
Why generate at build time instead of runtime?
- App starts faster
- Spec works even if source files change
- All instances serve the same spec
Alternative: Static File Serving
If you prefer not to use OpenApiModule, you can serve the spec as a static file:
import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
@Module({
imports: [
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..'),
serveRoot: '/api',
serveStaticOptions: {
index: false,
},
}),
],
})
export class AppModule {}Then access at /api/openapi.json.
Next Steps
- Swagger UI Recipe - Advanced Swagger UI configuration
- CI/CD Recipe - Generate specs in pipelines
- API Reference: OpenApiModule - Full API documentation