nestjs
NestJS
Commands
| Task | Command |
|---|---|
| Generate a module | pnpm exec nest generate module <name> |
| Generate a controller | pnpm exec nest generate controller <name> |
| Generate a service | pnpm exec nest generate service <name> |
| Generate a full resource | pnpm exec nest generate resource <name> |
| Generate a guard | pnpm exec nest generate guard <name> |
| Generate an interceptor | pnpm exec nest generate interceptor <name> |
| Generate a pipe | pnpm exec nest generate pipe <name> |
| Start in dev mode | pnpm start:dev |
| Build | pnpm build |
| Run tests | pnpm test |
Default action: When adding a new feature, prefer pnpm exec nest generate resource <name> to scaffold the full module, controller, and service in one step — then prune or extend as needed.
Always check
package.jsonscripts before running — script names may vary betweenauth-serverandemail-service.
Before generating — explore the project first
Before creating or modifying NestJS code, explore the project to understand:
- The module tree — read
app.module.tsto understand how existing feature modules are registered and which providers (Prisma, config, throttler, etc.) are available globally - The existing patterns — look at an existing module's controller, service, and DTO files to match folder structure, naming conventions, and Swagger decoration style
- How Prisma is injected — confirm whether the
DatabaseServiceis registered as a global provider or must be imported per feature module - How authentication is applied — check whether a
JwtAuthGuard(or equivalent) is bound globally viaAPP_GUARDor applied per-controller/route - What DTOs look like — check whether
class-validatordecorators andclass-transformerare in use, and how@ApiPropertyis applied alongside them
Fastify adapter
Services run on the Fastify HTTP adapter (@nestjs/platform-fastify), not Express. Be aware of these differences:
- Use
FastifyRequest/FastifyReplyinstead ofexpress.Request/express.Responsewhen typing injected request/response objects - Body parsing, file uploads, and multipart forms require Fastify-compatible plugins
- When manually setting headers or cookies via
@Res(), always pass{ passthrough: true }to avoid breaking NestJS's response lifecycle
Module structure
- Keep controllers thin — delegate all business logic to the service layer
- Keep services focused on a single domain — avoid growing them into god objects by extracting sub-services when needed
- Place shared types and interfaces in a
types/folder within the module
Swagger documentation
Before writing any Swagger decorators, read nest-cli.json to check whether the @nestjs/swagger CLI plugin is registered under compilerOptions.plugins. This significantly changes what you need to write manually:
-
Plugin active — TypeScript types on DTO properties are automatically introspected and emitted as Swagger schema metadata.
@ApiPropertydecorators on DTO fields are optional; the plugin infers types, optionality, andclass-validatorconstraints automatically. JSDoc comments on DTO fields are used as the Swaggerdescription. Only add@ApiPropertyexplicitly when you need to override the inferred value (e.g. a customexample,enum, ordescriptionthe plugin cannot derive). -
Plugin not active — every DTO field requires an explicit
@ApiProperty(or@ApiPropertyOptional) decorator; nothing is inferred from TypeScript types. -
Use typed DTO classes as response types — avoid
anyor raw object shapes so Swagger generates accurate schemas
Security patterns
Maintain the established security conventions on every new endpoint:
- Authentication — apply
@UseGuards(JwtAuthGuard)(or the project's equivalent guard) to all routes requiring an authenticated user; check whether a globalAPP_GUARDalready covers all routes before adding per-route guards - Rate limiting — the global
ThrottlerModuleenforces three windows (1 s / 10 s / 1 min); add@SkipThrottle()only for internal health or status endpoints - Helmet — configured globally at the application level; do not override CSP headers at the route level without a security review
- CORS — configured at the application level with dynamic origin validation; do not add ad-hoc
Access-Control-*headers to individual routes
DTOs and validation
Use class-validator and class-transformer for all request body DTOs:
ValidationPipeis applied globally — do not manually validate request bodies inside controllers
Workflow notes
- Run
pnpm testbefore committing to verify service and controller unit tests pass - Run
pnpm lintafter generating new files — ESLint enforces NestJS-specific rules - When adding a new database model, update the Prisma schema first — refer to the
prismaskill - Never instantiate services with
new— always inject them through NestJS's DI container - Keep
AppModuleclean — register feature modules rather than importing providers directly intoAppModule
More from dnd-mapp/ai-standards
pull-request
This skill should be used whenever the user asks to create a pull request, open a PR, or submit changes for review.
11prisma
>
10angular
>
10prettier
>
10commit
This skill should be used whenever the user asks to commit changes, create a git commit, or stage and commit files. Enforces Conventional Commits format for this project.
10eslint
>
10