NestJS course Β· Module 11: Swagger and OpenAPI
Swagger UI Customization - Decorating the Forum of Annals
In this lesson9
Just as the Forum Romanum was decorated with columns, statues, and frescoes, our Swagger UI can be customized visually and functionally. NestJS offers many options for personalizing the documentation interface.
SwaggerModule.setup() Options
The fourth parameter of the setup() method allows for advanced configuration:
1SwaggerModule.setup('api/docs', app, document, {
2 customSiteTitle: 'Chronicles of Imperium Romanum',
3 customCss: '.swagger-ui .topbar { background-color: #8B0000; }',
4 swaggerOptions: {
5 persistAuthorization: true,
6 docExpansion: 'none',
7 filter: true,
8 showRequestDuration: true,
9 tryItOutEnabled: true,
10 },
11});customSiteTitle - Name of the Notice Board
Changes the page title in the browser:
1SwaggerModule.setup('api/docs', app, document, {
2 customSiteTitle: 'Imperium API - Documentation',
3});customCss - Frescoes on the Walls
Allows you to add custom CSS styles to Swagger UI:
1SwaggerModule.setup('api/docs', app, document, {
2 customCss: `
3 .swagger-ui .topbar { background-color: #8B0000; }
4 .swagger-ui .topbar-wrapper img { content: url('/logo.png'); }
5 .swagger-ui .info .title { color: #8B0000; }
6 .swagger-ui .btn.execute { background-color: #8B0000; }
7 `,
8});swaggerOptions - Forum Regulations
Options controlling the behavior of Swagger UI:
| Option | Description | Default |
|---|---|---|
persistAuthorization | Keep JWT token after refresh | false |
docExpansion | Default section expansion | 'list' |
filter | Show search field | false |
showRequestDuration | Show response time | false |
tryItOutEnabled | Testing mode enabled by default | false |
defaultModelsExpandDepth | Model expansion depth | 1 |
defaultModelExpandDepth | Model field expansion depth | 1 |
1SwaggerModule.setup('api/docs', app, document, {
2 swaggerOptions: {
3 persistAuthorization: true,
4 docExpansion: 'none',
5 filter: true,
6 showRequestDuration: true,
7 },
8});addBearerAuth - Authorization Configuration
Full JWT authentication configuration in Swagger:
1const config = new DocumentBuilder()
2 .setTitle('Imperium API')
3 .addBearerAuth(
4 {
5 type: 'http',
6 scheme: 'bearer',
7 bearerFormat: 'JWT',
8 name: 'JWT',
9 description: 'Enter JWT token',
10 in: 'header',
11 },
12 'JWT-auth',
13 )
14 .build();After this configuration, an "Authorize" button will appear in Swagger UI where the user can enter their JWT token.
operationIdFactory - Operation Names
Every operation in OpenAPI has a unique operationId. You can control how they are generated:
1const document = SwaggerModule.createDocument(app, config, {
2 operationIdFactory: (controllerKey: string, methodKey: string) =>
3 methodKey,
4});By default, NestJS generates operationId in the format ControllerName_methodName. The above setting will use only the method name.
createDocument Options
The createDocument() method accepts additional options:
1const document = SwaggerModule.createDocument(app, config, {
2 // Include only selected modules
3 include: [LegionModule, ProvinceModule],
4
5 // Schema nesting depth
6 deepScanRoutes: true,
7
8 // Custom operationId generator
9 operationIdFactory: (controllerKey, methodKey) => methodKey,
10
11 // Additional models to include
12 extraModels: [ErrorResponseDto, PaginatedResponseDto],
13});Securing the Documentation
In a production environment, it is worth securing access to Swagger UI:
1import * as basicAuth from 'express-basic-auth';
2
3// Before SwaggerModule.setup()
4app.use(
5 '/api/docs',
6 basicAuth({
7 challenge: true,
8 users: { admin: 'imperiumSecret123' },
9 }),
10);
11
12SwaggerModule.setup('api/docs', app, document);Practical Exercise
Configure advanced Swagger UI options for the Imperium project:
Code for this lesson: src/main.ts
1// Swagger UI customization
2import { NestFactory } from '@nestjs/core';
3import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
4
5async function bootstrap() {
6 // const app = await NestFactory.create(AppModule);
7
8 const config = new DocumentBuilder()
9 .setTitle('Imperium Romanum API')
10 .setDescription('Imperium API Chronicles')
11 .setVersion('1.0')
12 // TODO: Add addBearerAuth with a full configuration:
13 // type: 'http', scheme: 'bearer', bearerFormat: 'JWT'
14 .build();
15
16 // const document = SwaggerModule.createDocument(app, config);
17
18 // TODO: Configure SwaggerModule.setup with options:
19 // customSiteTitle: 'Imperium API Chronicles'
20 // swaggerOptions:
21 // persistAuthorization: true
22 // docExpansion: 'none'
23 // filter: true
24 // showRequestDuration: true
25
26 // SwaggerModule.setup('api/docs', app, document, {
27 // // TODO: Add customSiteTitle
28 // // TODO: Add swaggerOptions
29 // });
30
31 console.log("Swagger UI: http://localhost:3000/api/docs");
32}
33
34bootstrap();
35
36console.log("=== Customization options ===");
37console.log("customSiteTitle - page title");
38console.log("customCss - custom CSS styles");
39console.log("swaggerOptions.persistAuthorization - keep the token");
40console.log("swaggerOptions.docExpansion - section expansion");
41console.log("swaggerOptions.filter - search field");
42console.log("swaggerOptions.showRequestDuration - response time");
43Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What does the persistAuthorization option do in swaggerOptions?
2. What does the customSiteTitle option change in the SwaggerModule.setup() configuration?
These are 2 of 3 questions for this lesson. Solve the rest in the game.
Hands-on tasks in the game
- Code editor
Complete the SwaggerModule.setup options with customSiteTitle and swaggerOptions
- Horizontal ordering
Arrange the elements of the addBearerAuth configuration in the correct order:
- Code editor
Add full Swagger documentation (tags, operation, params, responses, auth) to the gladiator controller