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

Cursor rules for a NestJS project
# 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.

How fenbs helps

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 account

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

How to set up NestJS rules with fenbs

  1. 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.
  2. Add the template above to your project's .cursor/rules/ directory and replace the commands with the actual scripts from your package.json.
  3. 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.
  4. 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.

Questions people ask.

Should I have separate rules files for the src/ subdirectories in NestJS?

Only if those directories have meaningfully different conventions. Most NestJS projects can share one rules file. If you have a large project with separate apps in a monorepo, scoped rules files per app directory are worth the added structure.

How do I write rules for a project that uses Prisma instead of TypeORM?

Replace the database access section with Prisma-specific rules: where the PrismaService is injected, which services may call it directly, and whether generated types are used as DTOs or wrapped in separate classes.

Can Cursor rules prevent an assistant from adding circular module dependencies?

Rules can instruct an assistant to ask before creating cross-module imports. They cannot detect circular dependencies automatically. Write the rule as a prompt: before importing from another module, check whether that module already imports from this one.

Where should decisions about API versioning live?

Versioning strategy belongs in fenbs as a Decision linked to the tasks that prompted it. The rules file can state which version prefix routes use; the reasoning about why versioning was introduced at a particular point stays in fenbs.

More in Prompts and skills for AI work

All Prompts and skills for AI work articles

Start with one thing.

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

There is nothing to set up first. Write one line and you’ve started.