From backend-overture
This skill provides backend TypeScript development rules including functions-over-classes design, NestJS/TypeORM patterns, layered error handling, streaming, and memory management. Automatically loaded when implementing backend TypeScript services, APIs, or when "NestJS", "backend TypeScript", "API service", "TypeORM", or "server-side TypeScript" are mentioned.
How this skill is triggered — by the user, by Claude, or both
Slash command
/backend-overture:typescript-rules-backendThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- **Functions Over Classes**: Prefer pure functions and function composition. Use classes only when the framework requires it (NestJS controllers/services, TypeORM entities)
Absolute Rule: any type is completely prohibited. It disables type checking and becomes a source of runtime errors.
any Type Alternatives (Priority Order)
unknown Type + Type Guards: Use for validating external input (API request bodies, environment variables, message queue payloads)Type Guard Implementation Pattern
function isCreateUserDto(value: unknown): value is CreateUserDto {
return typeof value === 'object' && value !== null && 'email' in value && 'name' in value
}
Modern Type Features
satisfies Operator: const config = { port: 3000 } satisfies AppConfig — Preserves inferenceconst Assertion: const ROLES = ['admin', 'user', 'viewer'] as const — Immutable and type-safetype UserId = string & { __brand: 'UserId' } — Distinguish domain identifierstype EventName = \on${Capitalize}`` — Express string patterns with typesType Safety in Backend Implementation
unknown, validate with Zod/class-validator before processingunknown, validate at startup — fail fast on missing required valuesunknown, validate with schema before processingType Safety in Data Flow
unknown) → Validation (Zod/class-validator) → DTO (Type Guaranteed) → ServiceType Complexity Management
Function Design
// ✅ Object parameter
function createUser({ name, email, role }: CreateUserParams): Promise<User> {}
NestJS Patterns (when using NestJS)
// ✅ Thin controller — delegates to service
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Post()
create(@Body() dto: CreateUserDto): Promise<UserResponseDto> {
return this.userService.create(dto)
}
}
TypeORM Patterns (when using TypeORM)
synchronize: true in productionDependency Injection
Asynchronous Processing
async/awaitPromise.all() for independent operations, Promise.allSettled() when partial failure is acceptableEnvironment Variables
process.env directly in business logic — always go through config layer// ✅ Centralized, validated config
const config = {
port: parseInt(process.env.PORT || '3000', 10),
dbUrl: requiredEnv('DATABASE_URL'),
redisUrl: process.env.REDIS_URL || 'redis://localhost:6379',
} satisfies AppConfig
function requiredEnv(key: string): string {
const value = process.env[key]
if (!value) throw new Error(`Missing required environment variable: ${key}`)
return value
}
Security
Format Rules
PascalCase, variables/functions in camelCase@/, @app/, etc.)Clean Code Principles
console.log()Absolute Rule: Error suppression prohibited. All errors must have log output and appropriate handling.
Layered Error Handling (Backend)
Three distinct layers, each with specific responsibilities:
API Layer (Controllers/Middleware)
Service Layer (Business Logic)
Repository Layer (Data Access)
// ✅ Layered error handling
// Repository layer
async findById(id: string): Promise<User> {
const user = await this.repository.findOne({ where: { id } })
if (!user) throw new NotFoundError(`User not found: ${id}`)
return user
}
// Service layer
async updateUser(id: string, dto: UpdateUserDto): Promise<User> {
const user = await this.userRepository.findById(id) // Throws NotFoundError
Object.assign(user, dto)
return this.userRepository.save(user)
}
// Controller layer (NestJS exception filter handles mapping)
@Put(':id')
async update(@Param('id') id: string, @Body() dto: UpdateUserDto): Promise<UserResponseDto> {
return this.userService.updateUser(id, dto)
}
Fail-Fast Principle: Fail quickly on errors to prevent continued processing in invalid states
// ✅ Required: Explicit failure
catch (error) {
logger.error('Processing failed', { error, context })
throw error
}
Custom Error Classes
export class AppError extends Error {
constructor(message: string, public readonly code: string, public readonly statusCode = 500) {
super(message)
this.name = this.constructor.name
}
}
// Purpose-specific: ValidationError(400), NotFoundError(404), ConflictError(409), ApiError(502)
Structured Logging
console.logStream Processing
pipeline() over .pipe() for proper error handling and cleanupimport { pipeline } from 'stream/promises'
// ✅ Stream large file processing
await pipeline(
createReadStream('input.csv'),
new CsvParser(),
new TransformStream(),
createWriteStream('output.json'),
)
Memory Leak Prevention
onModuleDestroy)WeakMap/WeakRef for caches that should not prevent garbage collectionBasic Policy
Implementation Procedure: Understand Current State → Gradual Changes → Behavior Verification → Final Validation
Priority: Duplicate Code Removal > Large Function Division > Complex Conditional Branch Simplification > Type Safety Improvement
npx claudepluginhub tundraray/overture --plugin backend-overtureProvides expert Node.js backend patterns for Express, NestJS, Fastify APIs including project structures, async error handlers, custom error classes, and global error handling.
Applies opinionated NestJS conventions for backends: modules, dependency injection, controllers/services, DTOs with class-validator, guards/interceptors/pipes, JWT auth, TypeORM/Prisma. Use for REST/GraphQL APIs.
Enforces NestJS best practices for modular architecture, dependency injection scoping, exception filters, class-validator DTO validation, and Drizzle ORM integration. Use when designing modules, providers, filters, DTOs, or ORM in NestJS apps.