Skills

Install

$ npx ai-agents-skills add --skill nest
Framework v1.1

Also Installs

NestJS

Scalable server apps with NestJS modules, dependency injection, and decorators.

When to Use

  • Modular server apps
  • Dependency injection
  • Scalable APIs

Don’t use for:

  • Single-file scripts/CLIs (use Node.js)
  • Lightweight edge functions (use Hono/Express)
  • Frontend-only projects

Critical Patterns

✅ REQUIRED: Module / Controller / Service Structure

Each feature in own module with controllers and providers.

// CORRECT: one module encapsulates the feature
@Module({
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}
// WRONG: registering all services in AppModule

✅ REQUIRED: Dependency Injection

Inject via constructor; never instantiate manually.

// CORRECT: let the DI container manage instances
@Controller("users")
export class UsersController {
  constructor(private readonly usersService: UsersService) {}
  @Get(":id")
  findOne(@Param("id") id: string) {
    return this.usersService.findOne(id);
  }
}
// WRONG: const service = new UsersService()

✅ REQUIRED: Guards, Pipes, and Interceptors

Built-in lifecycle hooks for cross-cutting concerns.

// CORRECT: guard for auth, pipe for validation, interceptor for transform
@UseGuards(AuthGuard)
@UsePipes(new ValidationPipe({ whitelist: true }))
@UseInterceptors(ClassSerializerInterceptor)
@Controller("users")
export class UsersController {}

✅ REQUIRED: DTOs with class-validator

DTOs with decorators for auto-validation.

export class CreateUserDto {
  @IsString() @MinLength(2) name: string;
  @IsEmail() email: string;
  @IsOptional() @IsString() bio?: string;
}
@Post()
create(@Body() dto: CreateUserDto) {
  return this.usersService.create(dto);
}

✅ REQUIRED: Exception Filters

Map domain errors to HTTP responses centrally.

@Catch(DomainException)
export class DomainExceptionFilter implements ExceptionFilter {
  catch(exception: DomainException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    ctx.getResponse().status(exception.status).json({
      error: exception.message,
    });
  }
}

Decision Tree

REST API?
  → @Controller with HTTP method decorators

GraphQL API?
  → @Resolver with @nestjs/graphql

Shared business logic?
  → Extract into an @Injectable() service

Request validation?
  → Apply ValidationPipe globally or per-route

Auth check?
  → Implement a Guard with canActivate

Response shaping?
  → Use an Interceptor or Serializer

Background work?
  → @nestjs/bull or @nestjs/schedule

Config secrets?
  → ConfigModule.forRoot() with .env

Example

@Controller("users")
export class UsersController {
  constructor(private readonly users: UsersService) {}
  @Get()
  findAll() { return this.users.findAll(); }
  @Post()
  @UsePipes(new ValidationPipe({ whitelist: true }))
  create(@Body() dto: CreateUserDto) { return this.users.create(dto); }
  @Get(":id")
  async findOne(@Param("id", ParseIntPipe) id: number) {
    const user = await this.users.findOne(id);
    if (!user) throw new NotFoundException("User not found");
    return user;
  }
}

Edge Cases

  • Circular deps: Use forwardRef(() => SomeModule) for mutual dependencies.
  • Request-scoped providers: Default singleton; Scope.REQUEST hurts performance.
  • Module order: Import ConfigModule before dependent modules.
  • Global pipes: app.useGlobalPipes() skips DI; use APP_PIPE provider for injected deps.
  • Test mocks: Override providers in Test.createTestingModule(), not imports.

Checklist

  • Each feature has its own module with controllers and providers
  • Services are injected via constructors, never manually instantiated
  • ValidationPipe with whitelist: true is applied globally or per-route
  • DTOs use class-validator decorators for all input
  • Guards protect authenticated routes
  • Exception filters map domain errors to HTTP status codes
  • ConfigModule loads environment variables before dependent modules
  • Unit tests mock providers via the testing module

Resources