NestJS 10 modular architecture, services, DTOs, guards, and API patterns.
Install
npx skillscat add tachfineamnay/lumirav2/backend-architecture-nestjs Install via the SkillsCat registry.
SKILL.md
Backend Architecture (NestJS)
Context
- Framework: NestJS 10
- Location:
apps/api/ - Port: 3001 (dev), 3001 (prod via Coolify)
- Architecture: Modular monolith with strict separation
Directory Structure
apps/api/src/
├── modules/
│ ├── auth/ # Authentication & guards
│ ├── users/ # User management
│ ├── missions/ # Mission CRUD
│ ├── wall/ # Feed/Wall feature
│ └── insights/ # AI insights
├── services/
│ └── factory/ # Business logic factories
│ ├── DigitalSoulService.ts
│ └── VertexOracle.ts
├── common/
│ ├── decorators/
│ ├── guards/
│ ├── interceptors/
│ └── pipes/
└── main.tsCore Principles
- Dependency Injection: All services are injectable. No global state.
- Factory Pattern: Complex object creation via Factories (e.g.,
PdfFactory). - Saga Pattern: Long processes orchestrated in dedicated services.
- DTOs Everywhere: Validate all inputs with
class-validator.
Module Structure
// missions/missions.module.ts
@Module({
imports: [DatabaseModule],
controllers: [MissionsController],
providers: [MissionsService],
exports: [MissionsService],
})
export class MissionsModule {}Service Pattern
@Injectable()
export class MissionsService {
constructor(private readonly prisma: PrismaService) {}
async findAll(filters: MissionFiltersDto): Promise<Mission[]> {
return this.prisma.mission.findMany({
where: this.buildWhereClause(filters),
include: { user: true },
});
}
}DTO Validation
// dto/create-mission.dto.ts
export class CreateMissionDto {
@IsString()
@MinLength(10)
title: string;
@IsEnum(MissionType)
type: MissionType;
@IsOptional()
@IsDateString()
startDate?: string;
}Guards
JWT Authentication
@UseGuards(JwtAuthGuard)
@Get('profile')
getProfile(@CurrentUser() user: User) {
return user;
}Role-Based Access
@Roles(Role.ADMIN, Role.EXPERT)
@UseGuards(JwtAuthGuard, RolesGuard)
@Get('admin/users')
getAllUsers() { ... }Key Services
DigitalSoulService
Orchestrates AI generation workflow:
@Injectable()
export class DigitalSoulService {
async processOrder(orderId: string): Promise<void> {
// 1. Fetch order
// 2. Call VertexOracle for AI analysis
// 3. Generate PDF via PdfFactory
// 4. Store results in DB (transaction)
// 5. Notify user
}
}VertexOracle
Encapsulates Vertex AI communication:
@Injectable()
export class VertexOracle {
async generateReading(input: ReadingInput): Promise<ReadingOutput> {
// Prompt engineering + API call + JSON parsing
}
}Error Handling
// Use standard NestJS exceptions
throw new NotFoundException(`Mission ${id} not found`);
throw new BadRequestException('Invalid date range');
throw new ForbiddenException('Access denied');
// Global exception filter handles formattingLogging
import { Logger } from '@nestjs/common';
@Injectable()
export class MissionsService {
private readonly logger = new Logger(MissionsService.name);
async create(dto: CreateMissionDto) {
this.logger.log(`Creating mission: ${dto.title}`);
// Never use console.log
}
}