GetMan GetMan

Replace @nestjs/swagger's Default UI

@nestjs/swagger reads your controllers’ decorators (@ApiTags, @ApiProperty, and the rest) and builds a complete OpenAPI document at boot time — SwaggerModule.setup() is what then serves that document through Swagger UI. The document-building half is the useful part; the UI half is what this guide replaces.

Generate the document as usual

Nothing changes about how the document itself gets built:

const config = new DocumentBuilder()
  .setTitle('My API')
  .setVersion('1.0')
  .build();

const document = SwaggerModule.createDocument(app, config);

Stop calling SwaggerModule.setup(), expose the JSON directly

SwaggerModule.setup('api', app, document) is what mounts Swagger UI — remove that call (or leave it under a path you no longer link to), and expose the raw document yourself instead:

app.getHttpAdapter().get('/openapi.json', (req, res) => res.json(document));

This works because Nest’s default platform is Express under the hood, so getHttpAdapter() gives you the same get() you’d use directly in Express.

Serve GetMan at your docs route

Add one more route that returns GetMan’s page instead of Swagger UI’s:

app.getHttpAdapter().get('/api-docs', (req, res) => {
  res.type('html').send(`
    <div id="api-docs" style="height: 100vh"></div>
    <script src="https://cdn.getman.dev/latest/getman-ui.js"></script>
    <script>
      GetMan.launch(document.getElementById('api-docs'), { url: '/openapi.json' });
    </script>
  `);
});

Register both routes in main.ts before app.listen(), the same place SwaggerModule.setup() would normally go. Everything upstream of the document — decorators, DocumentBuilder config, module structure — stays exactly as it was.

See the Swagger UI alternative comparison for the feature differences this swap buys you beyond just the routing change above.

Try it with your own spec

Paste any OpenAPI or Swagger URL and see it rendered live — no signup, no install.

Open the explorer