Monorepo Setup
Generate OpenAPI specs for multiple NestJS applications
When your project contains multiple NestJS applications, you can generate separate OpenAPI specifications for each.
Project Structure
Typical monorepo layout:
my-monorepo/
├── apps/
│ ├── backend-api/
│ │ ├── src/
│ │ │ └── app.module.ts
│ │ └── openapi.config.ts
│ ├── admin-api/
│ │ ├── src/
│ │ │ └── app.module.ts
│ │ └── openapi.config.ts
│ └── public-api/
│ ├── src/
│ │ └── app.module.ts
│ └── openapi.config.ts
├── libs/
│ └── shared/
│ └── src/
│ └── dto/
├── package.json
└── tsconfig.jsonPer-App Configuration
Create a config file for each application:
// apps/backend-api/openapi.config.ts
import { } from 'nestjs-openapi';
export default ({
: 'openapi.json',
: {
: 'src/app.module.ts',
: '../../tsconfig.json',
: ['src/**/*.dto.ts', '../../libs/shared/src/**/*.dto.ts'],
},
: {
: {
: 'Backend API',
: '1.0.0',
: 'Internal backend services',
},
: [
{ : 'https://backend.example.com', : 'Production' },
],
},
: {
: '/api',
},
});// apps/admin-api/openapi.config.ts
import { defineConfig } from 'nestjs-openapi';
export default defineConfig({
output: 'openapi.json',
files: {
entry: 'src/app.module.ts',
tsconfig: '../../tsconfig.json',
dtoGlob: ['src/**/*.dto.ts', '../../libs/shared/src/**/*.dto.ts'],
},
openapi: {
info: {
title: 'Admin API',
version: '1.0.0',
description: 'Administration interface',
},
servers: [{ url: 'https://admin.example.com', description: 'Production' }],
security: {
schemes: [
{
name: 'adminAuth',
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
},
],
global: [{ adminAuth: [] }],
},
},
});NPM Scripts
Add scripts to generate specs for all apps:
{
"scripts": {
"openapi": "npm run openapi:backend && npm run openapi:admin && npm run openapi:public",
"openapi:backend": "nestjs-openapi generate -c apps/backend-api/openapi.config.ts",
"openapi:admin": "nestjs-openapi generate -c apps/admin-api/openapi.config.ts",
"openapi:public": "nestjs-openapi generate -c apps/public-api/openapi.config.ts"
}
}Run all at once:
npm run openapiOr generate individually:
npm run openapi:backendShared Base Configuration
Use config inheritance to avoid duplication:
// configs/base-openapi.config.ts
import { defineConfig } from 'nestjs-openapi';
export default defineConfig({
format: 'json', // or 'yaml'
files: {
tsconfig: '../../tsconfig.json',
exclude: ['**/*.spec.ts', '**/*.test.ts'],
},
options: {
extractValidation: true,
excludeDecorators: ['ApiExcludeEndpoint', 'Internal'],
},
});The extends field is not executed by the current generator. Import and
spread your base config instead of relying on inheritance.
// apps/backend-api/openapi.config.ts
import { defineConfig } from 'nestjs-openapi';
import base from '../../configs/base-openapi.config';
export default defineConfig({
...base,
output: 'openapi.json',
files: {
...base.files,
entry: 'src/app.module.ts',
dtoGlob: ['src/**/*.dto.ts', '../../libs/shared/src/**/*.dto.ts'],
},
openapi: {
...base.openapi,
info: {
...base.openapi.info,
title: 'Backend API',
version: '1.0.0',
},
},
});Nx Workspaces
For Nx monorepos, you can use project-level scripts:
// apps/backend-api/project.json
{
"name": "backend-api",
"targets": {
"openapi": {
"executor": "nx:run-commands",
"options": {
"command": "npx nestjs-openapi generate -c apps/backend-api/openapi.config.ts"
}
}
}
}Run with Nx:
# Single app
nx openapi backend-api
# All apps
nx run-many --target=openapiTurborepo
For Turborepo monorepos:
// turbo.json
{
"pipeline": {
"openapi": {
"dependsOn": ["^build"],
"outputs": ["openapi.json"]
}
}
}turbo run openapiShared DTOs
When apps share DTOs from a library:
// libs/shared/src/dto/user.dto.ts
export class UserDto {
id: string;
email: string;
name: string;
}
export class CreateUserDto {
email: string;
name: string;
}Include the shared library in dtoGlob:
// apps/backend-api/openapi.config.ts
files: {
entry: 'src/app.module.ts',
dtoGlob: [
'src/**/*.dto.ts',
'../../libs/shared/src/**/*.dto.ts',
],
}Output Organization
Keep generated specs organized:
my-monorepo/
├── apps/
│ ├── backend-api/
│ │ ├── openapi.json # Generated here
│ │ └── openapi.config.ts
│ └── admin-api/
│ ├── openapi.json # Generated here
│ └── openapi.config.ts
├── docs/
│ └── openapi/ # Or centralize here
│ ├── backend-api.json
│ └── admin-api.jsonCentralized output:
// apps/backend-api/openapi.config.ts
output: '../../docs/openapi/backend-api.json',Parallel Generation
Generate all specs in parallel using npm-run-all:
npm install -D npm-run-all{
"scripts": {
"openapi": "run-p openapi:*",
"openapi:backend": "nestjs-openapi generate -c apps/backend-api/openapi.config.ts",
"openapi:admin": "nestjs-openapi generate -c apps/admin-api/openapi.config.ts",
"openapi:public": "nestjs-openapi generate -c apps/public-api/openapi.config.ts"
}
}Complete Example
// apps/backend-api/openapi.config.ts
import { defineConfig } from 'nestjs-openapi';
import base from '../../configs/base-openapi.config';
export default defineConfig({
...base,
output: 'openapi.json',
files: {
...base.files,
entry: 'src/app.module.ts',
dtoGlob: [
'src/**/*.dto.ts',
'../../libs/shared/src/dto/**/*.ts',
'../../libs/entities/src/**/*.entity.ts',
],
},
openapi: {
...base.openapi,
info: {
...base.openapi.info,
title: 'Backend API',
version: '1.0.0',
description: 'Internal backend services for the platform',
contact: {
name: 'Backend Team',
email: 'backend@example.com',
},
},
servers: [
{ url: 'https://backend.example.com', description: 'Production' },
{ url: 'https://staging-backend.example.com', description: 'Staging' },
{ url: 'http://localhost:3001', description: 'Development' },
],
tags: [
{ name: 'users', description: 'User management' },
{ name: 'orders', description: 'Order processing' },
{ name: 'inventory', description: 'Inventory management' },
],
},
options: {
basePath: '/api/v1',
},
});Next Steps
- CI/CD Recipe - Automate generation in pipelines
- OpenAPI Clients Recipe - Generate typed clients
- Configuration Guide - Full config reference