AI Skill Report Card

Building NestJS APIs

A-82·May 4, 2026·Source: Web

NestJS API Development

15 / 15
TypeScript
// app.module.ts import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ConfigModule } from '@nestjs/config'; import { UsersModule } from './users/users.module'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true }), TypeOrmModule.forRoot({ type: 'postgres', host: process.env.DB_HOST, port: +process.env.DB_PORT, username: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, autoLoadEntities: true, synchronize: process.env.NODE_ENV !== 'production', }), UsersModule, ], }) export class AppModule {}
Recommendation
Reduce verbosity in workflow explanations - Claude understands NestJS basics and doesn't need every decorator explained
14 / 15

Progress:

  • Set up module structure with proper separation of concerns
  • Define entities with TypeORM decorators
  • Create DTOs with class-validator
  • Implement services with dependency injection
  • Build controllers with proper HTTP methods
  • Add authentication guards and middleware
  • Configure database connections and migrations
  • Implement error handling and logging

Step 1: Module Architecture

TypeScript
// users/users.module.ts @Module({ imports: [TypeOrmModule.forFeature([User])], controllers: [UsersController], providers: [UsersService], exports: [UsersService], }) export class UsersModule {}

Step 2: Entity Definition

TypeScript
// users/entities/user.entity.ts @Entity() export class User { @PrimaryGeneratedColumn('uuid') id: string; @Column({ unique: true }) email: string; @Column() @Exclude() password: string; @CreateDateColumn() createdAt: Date; }

Step 3: DTO Validation

TypeScript
// users/dto/create-user.dto.ts export class CreateUserDto { @IsEmail() @IsNotEmpty() email: string; @IsString() @MinLength(8) @Matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/) password: string; }

Step 4: Service Implementation

TypeScript
// users/users.service.ts @Injectable() export class UsersService { constructor( @InjectRepository(User) private usersRepository: Repository<User>, ) {} async create(createUserDto: CreateUserDto): Promise<User> { const hashedPassword = await bcrypt.hash(createUserDto.password, 10); const user = this.usersRepository.create({ ...createUserDto, password: hashedPassword, }); return this.usersRepository.save(user); } }

Step 5: Controller Setup

TypeScript
// users/users.controller.ts @Controller('users') @UseGuards(JwtAuthGuard) export class UsersController { constructor(private readonly usersService: UsersService) {} @Post() @UseInterceptors(ClassSerializerInterceptor) async create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); } }
Recommendation
Add more concrete input/output examples showing actual API requests and responses, not just code snippets
18 / 20

Example 1: JWT Authentication Guard Input: Need to protect routes with JWT authentication Output:

TypeScript
@Injectable() export class JwtAuthGuard extends AuthGuard('jwt') { canActivate(context: ExecutionContext) { return super.canActivate(context); } handleRequest(err, user, info) { if (err || !user) { throw err || new UnauthorizedException(); } return user; } }

Example 2: Global Exception Filter Input: Handle all unhandled exceptions consistently Output:

TypeScript
@Catch() export class AllExceptionsFilter implements ExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); const request = ctx.getRequest(); const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR; response.status(status).json({ statusCode: status, timestamp: new Date().toISOString(), path: request.url, message: exception instanceof HttpException ? exception.getResponse() : 'Internal server error', }); } }
Recommendation
Include a complete working example with database setup and authentication flow rather than scattered code pieces
  • Module Organization: One module per business domain, keep modules focused and cohesive
  • Dependency Injection: Use constructor injection, avoid circular dependencies
  • DTOs: Always validate input with class-validator, separate DTOs for create/update operations
  • Error Handling: Use built-in HTTP exceptions, implement global exception filters
  • Security: Hash passwords with bcrypt, use JWT for stateless auth, implement rate limiting
  • Database: Use transactions for multi-step operations, implement soft deletes where needed
  • Testing: Write unit tests for services, integration tests for controllers
  • Configuration: Use ConfigModule for environment variables, validate config on startup
  • Don't use any type - leverage TypeScript's type system fully
  • Don't expose entities directly - always use DTOs for API responses
  • Don't forget to validate input - use ValidationPipe globally
  • Don't ignore database migrations - use TypeORM migrations in production
  • Don't store secrets in code - use environment variables and config validation
  • Don't create god modules - keep modules small and focused
  • Don't bypass guards - apply authentication/authorization consistently
  • Don't ignore error logging - implement structured logging with context
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
15/15
Workflow
14/15
Examples
18/20
Completeness
17/20
Format
15/15
Conciseness
13/15