NestJS Patterns
SkillDev toolsNestJS best practices, module architecture, DTOs, Guards, Interceptors, and common patterns. Use when building or reviewing NestJS backend services.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the NestJS Patterns skill
What this skill tells your AI
The instructions your AI receives, as published by sabahattink/antigravity-fullstack-hq in skills/nestjs-patterns/SKILL.md and read by ahel’s review.
Module Structure
src/modules/users/
├── users.module.ts
├── users.controller.ts
├── users.service.ts
├── dto/
│ ├── create-user.dto.ts
│ └── update-user.dto.ts
├── entities/
│ └── user.entity.ts
└── guards/
└── user-owner.guard.ts
Key Patterns
Module Definition
@Module({
imports: [PrismaModule],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}
DTOs with Validation
import { IsEmail, IsString, MinLength } from 'class-validator'
export class CreateUserDto {
@IsEmail()
email: string
@IsString()
@MinLength(8)
password: string
}
Service Pattern
@Injectable()
export class UsersService {
constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateUserDto) {
return this.prisma.user.create({ data: dto })
}
async findOne(id: string) {
const user = await this.prisma.user.findUnique({ where: { id } })
if (!user) throw new NotFoundException()
return user
}
}
Controller Pattern
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
@HttpCode(HttpStatus.CREATED)
create(@Body() dto: CreateUserDto) {
return this.usersService.create(dto)
}
@Get(':id')
@UseGuards(JwtAuthGuard)
findOne(@Param('id') id: string) {
return this.usersService.findOne(id)
}
}
Guards
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
@Injectable()
export class ResourceOwnerGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest()
return request.user.id === request.params.id
}
}
Custom Decorators
export const CurrentUser = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest()
return data ? request.user?.[data] : request.user
},
)
// Usage: @CurrentUser() user or @CurrentUser('id') id
Forbidden Patterns
- Business logic in controllers
- Returning sensitive data (passwords)
- No validation on inputs
- Hardcoded secrets
- Skipping error handling
Signals
- GitHub stars
- 30
- Forks
- 9
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
nestjs-patterns-sabahattink- Source
- github.com/sabahattink/antigravity-fullstack-hq