AgentStack
SKILL verified MIT Self-run

Nestjs Best Practices

skill-ejirocodes-agent-skills-nestjs-best-practices · by ejirocodes

NestJS 11+ best practices for enterprise Node.js applications with TypeScript. Use when writing, reviewing, or refactoring NestJS controllers, services, modules, or APIs. Triggers on: NestJS modules, controllers, providers, dependency injection, @Injectable, @Controller, @Module, middleware, guards, interceptors, pipes, exception filters, ValidationPipe, class-validator, class-transformer, DTOs,…

No reviews yet
0 installs
15 views
0.0% view→install

Install

$ agentstack add skill-ejirocodes-agent-skills-nestjs-best-practices

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Nestjs Best Practices? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

NestJS 11 Best Practices

Quick Reference

| Topic | When to Use | Reference | |-------|-------------|-----------| | Core Architecture | Modules, Providers, DI, forwardRef, custom decorators | [core-architecture.md](references/core-architecture.md) | | Request Lifecycle | Middleware, Guards, Interceptors, Pipes, Filters | [request-lifecycle.md](references/request-lifecycle.md) | | Validation & Pipes | DTOs, class-validator, ValidationPipe, transforms | [validation-pipes.md](references/validation-pipes.md) | | Authentication | JWT, Passport, Guards, Local/OAuth strategies, RBAC | [authentication.md](references/authentication.md) | | Database | TypeORM, Prisma, Drizzle ORM, repository patterns | [database-integration.md](references/database-integration.md) | | Testing | Unit tests, E2E tests, mocking providers | [testing.md](references/testing.md) | | OpenAPI & GraphQL | Swagger decorators, resolvers, subscriptions | [openapi-graphql.md](references/openapi-graphql.md) | | Microservices | TCP, Redis, NATS, Kafka patterns | [microservices.md](references/microservices.md) |

Essential Patterns

Module with Providers

@Module({
  imports: [DatabaseModule],
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService], // Export for other modules
})
export class UsersModule {}

Controller with Validation

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }

  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number) {
    return this.usersService.findOne(id);
  }
}

DTO with Validation

import { IsEmail, IsString, MinLength, IsOptional } from 'class-validator';

export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsString()
  @MinLength(8)
  password: string;

  @IsOptional()
  @IsString()
  name?: string;
}

Exception Filter

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      message: exception.message,
      timestamp: new Date().toISOString(),
    });
  }
}

Guard with JWT

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  canActivate(context: ExecutionContext) {
    return super.canActivate(context);
  }
}

NestJS 11 Breaking Changes

  • Express v5: Wildcards must be named (e.g., *splat), optional params use braces /:file{.:ext}
  • Node.js 20+: Minimum required version
  • Fastify v5: Updated adapter for Fastify users
  • Dynamic Modules: Same module with identical config imported multiple times = separate instances

Common Mistakes

  1. Not using forwardRef() for circular deps - Causes "cannot resolve dependency" errors; wrap in forwardRef(() => ModuleName)
  2. Throwing plain errors instead of HttpException - Loses status codes, breaks exception filters; use throw new BadRequestException('message')
  3. Missing @Injectable() decorator - Provider won't be injectable; always decorate services
  4. Global ValidationPipe without whitelist: true - Allows unexpected properties; set whitelist: true, forbidNonWhitelisted: true
  5. Importing modules instead of exporting providers - Use exports array to share providers across modules
  6. Async config without ConfigModule.forRoot() - ConfigService undefined; import ConfigModule in AppModule
  7. Testing without overrideProvider() - Uses real services in unit tests; mock dependencies with overrideProvider(Service).useValue(mock)
  8. E2E tests sharing database state - No isolation between tests; use transactions or truncate tables in beforeEach

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.