Cursor Rules for NestJS: Modules, Validation, and Tests
NestJS has strong conventions about module boundaries, dependency injection, validation with class-validator, and testing with Jest. These Cursor rules template captures what an AI assistant needs to follow them consistently.
Updated 6 min read
Cursor rules for NestJS tell the AI assistant how modules are organized, how providers are injected, how incoming data is validated, and which commands run the tests. Without these rules, an assistant will produce code that follows NestJS conventions in general but violates the specific structure your project has established — injecting providers from the wrong module, skipping validation decorators, or creating a new module when the work belongs in an existing one.
The API design decisions that explain why the modules are structured the way they are belong in fenbs alongside the tasks. An assistant that reads both the rules file and the project context starts with the current architecture in mind, not just the framework defaults.
What NestJS rules should cover
- Module structure: how modules are named, where they live, and whether the project follows domain, feature, or layer-based organization.
- Dependency injection: constructor injection only, no property injection, how to get a provider across module boundaries.
- Validation: class-validator and class-transformer, where DTOs live, and which validation pipe is global.
- Exception handling: global exception filters, HTTP exceptions versus custom exceptions, where error transformation happens.
- Database access: TypeORM, Prisma, or Mongoose, where repository or service calls happen, and whether queries belong in services or repositories.
- Test setup: the exact Jest commands, how to bootstrap a testing module, and whether to use supertest for e2e tests.
A starting template
# NestJS project rules ## Build and run - Build: npm run build - Test (unit): npm run test - Test (e2e): npm run test:e2e - Dev server: npm run start:dev ## Module organization - One module per feature domain in src/<domain>/ - Shared utilities go in src/common/ or src/shared/ - Do not create a new module without asking; check if an existing one fits. ## Dependency injection - Use constructor injection only; no @Inject() on properties. - Export only the providers other modules need; do not export everything. - Use forFeature() for TypeORM repositories; do not import the entity module directly. ## Validation - All incoming data goes through a DTO with class-validator decorators. - DTOs live in the same directory as the controller that uses them. - The global ValidationPipe is configured in main.ts; do not add a second one. ## Controllers - Controllers handle HTTP only. No business logic in controllers. - Use guards for authentication and authorization checks. - Response transformation happens in interceptors, not controllers. ## Tests - Unit tests mock all dependencies using jest.fn() or NestJS testing utilities. - E2e tests use a real testing module bootstrapped with Test.createTestingModule().
Module boundary rules in practice
Module boundaries are the most important convention to get right in NestJS. An assistant that imports a repository directly instead of going through the module's public API creates a circular dependency or a tight coupling that is hard to refactor later. Write the rules to make the module boundaries explicit: which modules export which providers, and how cross-module access is supposed to work.
If your project uses a shared module for utilities, say what belongs there and what does not. A shared module that accumulates everything becomes a hidden coupling point. Rules about what belongs in shared versus in a domain module prevent this drift over time.
API design decisions and fenbs
Why does the project use TypeORM repositories instead of Prisma? Why is authentication handled through a global guard instead of per-route? Why was a particular module split into two? Those decisions were made for reasons that the code does not surface.
Recording them in fenbs as Decisions means an assistant reading the project context before starting can understand the intent behind the architecture, not just follow the pattern it sees in existing files. When the architecture evolves, a new Decision captures the change and the reason.
Keep your API design decisions where every assistant finds them
Add the architectural decisions behind your NestJS setup to fenbs: ORM choice, authentication approach, module organization strategy. Connected AI apps read the project context before writing code, so they know why the structure is what it is, not just how to match it.
Create a free accountFree for one person · No credit card · Works with Claude, ChatGPT, Cursor and more
How to set up NestJS rules with fenbs
- Create a free account and add your NestJS project to fenbs. Record the API architecture decisions: ORM choice, authentication strategy, how module boundaries are defined.
- Add the template above to your project's
.cursor/rules/directory and replace the commands with the actual scripts from yourpackage.json. - Connect Cursor to fenbs over MCP from Integrations. Ask the assistant to read the project context at session start, including any Decisions about module organization.
- When the architecture changes — a new authentication approach, a refactored module structure — update the Decision in fenbs and the rules file together.
Interceptors, guards, and pipes in practice
NestJS interceptors, guards, and pipes each run at a different stage of the request lifecycle. An assistant that uses the wrong mechanism for the wrong stage produces code that appears to work but fails under edge cases: a guard that should reject a request before the controller runs, being moved to an interceptor that runs after. Write rules that say which mechanism handles which concern.
If your project uses a global guard for authentication, add a rule that says so, and state what that means for new endpoints: they are authenticated by default, and any exception requires an explicit decorator. That single rule prevents the common mistake of creating an unauthenticated endpoint because the guard was not applied.
Database migration rules
Migrations are some of the highest-risk actions an AI assistant can take in a backend project. A NestJS project using TypeORM or Prisma has a migration workflow, and an assistant that generates a migration without following that workflow may produce one that runs in the wrong order, conflicts with an existing migration, or applies to the wrong environment.
Add a migration rule with the same specificity as the template's module rule: the assistant may generate a migration, but must ask before running it. State which command generates and which runs migrations, and note whether migrations are reviewed before they land in the main branch. A one-line rule about requiring review prevents most migration-related incidents.
What to watch for
NestJS generates a lot of boilerplate through its CLI. If your team uses the CLI for scaffolding, add a note about which CLI commands are standard and which the assistant should not run without asking. The nest generate command creates files in specific directories that may conflict with your module organization.
Global pipes, filters, guards, and interceptors configured in main.ts apply to every request. An assistant that adds a second global pipe or wraps the existing one creates behavior that is hard to debug. Add an explicit rule: do not change main.ts without asking. See Cursor vs VS Code if your team is deciding between editors for TypeScript projects.