smithery/joseaplwork

NestJS API Development

NestJS backend conventions, controller patterns, HTTP verbs, guards, and service layer practices.

Installation

$ npx skills add smithery/joseaplwork --skill nestjs-api-development

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/joseaplwork.

npx skills add smithery/joseaplwork

Browse all from smithery/joseaplwork

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,907 B
  • docs SUMMARY.md 127 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

NestJS API Development

This skill provides patterns and conventions for building the NestJS backend API.

When to Use

  • When creating or modifying API controllers in apps/api/
  • When implementing endpoints and routes
  • When working with guards and decorators
  • When structuring service layers
  • When handling errors and responses

NestJS Conventions

Decorators and Routing

  • Use decorators for routing (@Get, @Post, @Patch, @Delete)
  • Use guards for authentication and authorization
  • Use decorators for extracting request data (@Body, @Param, @Query)

Controller Structure

Controllers should follow this pattern:

@Controller('participant')
export class ParticipantController {
  constructor(private readonly participantService: ParticipantService) {}

  @Get()
  findAll(): Promise<Participant[]> {
    return this.participantService.findAll()
  }

  @Get(':id')
  findOne(@Param('id') id: string): Promise<Participant> {
    return this.participantService.findOne(id)
  }

  @Post()
  create(@Body() payload: CreateParticipantDto): Promise<Participant> {
    return this.participantService.create(payload)
  }

  @Patch(':id')
  update(
    @Param('id') id: string,
    @Body() payload: UpdateParticipantDto,
  ): Promise<Participant> {
    return this.participantService.update(id, payload)
  }

  @Delete(':id')
  delete(@Param('id') id: string): Promise<void> {
    return this.participantService.delete(id)
  }
}

HTTP Verb Usage

Use the correct HTTP verbs for operations:

  • GET - Retrieve resources (list or single item)
  • POST - Create new resources
  • PATCH - Partial updates (preferred over PUT)
  • DELETE - Remove resources

Important

Always match the HTTP verb used in the frontend service. If the frontend uses .patch(), the controller must use @Patch().

Guards and Decorators

Authentication and Authorization

  • Use @UseGuards() for authentication/authorization
  • Create custom decorators for common patterns
  • Use @IsPublic() decorator for unauthenticated endpoints

Example

@Controller('participant')
@UseGuards(AuthGuard, PermissionsGuard)
export class ParticipantController {
  @Get()
  @Permissions(Permission.PARTICIPANT_READ)
  findAll(): Promise<Participant[]> {
    return this.participantService.findAll()
  }

  @Post('public')
  @IsPublic()
  createPublic(@Body() payload: CreateParticipantDto): Promise<Participant> {
    return this.participantService.create(payload)
  }
}

Service Layer

Best Practices

  • Keep business logic in services, not controllers
  • Services should be injectable and testable
  • Use TypeORM entities for database operations
  • Services handle data transformation and validation

Example

@Injectable()
export class ParticipantService {
  constructor(
    @InjectRepository(Participant)
    private readonly participantRepository: Repository<Participant>,
  ) {}

  async create(payload: CreateParticipantDto): Promise<Participant> {
    const participant = this.participantRepository.create(payload)
    return await this.participantRepository.save(participant)
  }

  async update(
    id: string,
    payload: UpdateParticipantDto,
  ): Promise<Participant> {
    await this.participantRepository.update(id, payload)
    return await this.findOne(id)
  }
}

Error Handling

Best Practices

  • Use NestJS built-in exceptions (BadRequestException, NotFoundException, etc.)
  • Avoid console.log for debugging in production code
  • Return appropriate HTTP status codes
  • Provide meaningful error messages

Example

async findOne(id: string): Promise<Participant> {
  const participant = await this.participantRepository.findOne({ where: { id } })

  if (!participant) {
    throw new NotFoundException(`Participant with ID ${id} not found`)
  }

  return participant
}

DTOs and Validation

  • Use DTOs (Data Transfer Objects) for request/response validation
  • Use class-validator decorators for validation
  • Keep DTOs in the same module or a shared location

Example

export class CreateParticipantDto {
  @IsString()
  @IsNotEmpty()
  name: string

  @IsEmail()
  email: string

  @IsString()
  @MinLength(6)
  password: string
}

Instructions

  1. Controllers: Use appropriate decorators, keep controllers thin (delegate to services)
  2. HTTP verbs: Match frontend HTTP methods (PATCH for updates, not PUT)
  3. Guards: Use guards for authentication/authorization, mark public endpoints
  4. Services: Keep business logic in services, make them testable
  5. Error handling: Use NestJS exceptions, avoid console.log in production
  6. DTOs: Use DTOs with validation for request/response data