From qe-framework
Scaffolds NestJS modules, controllers, services, DTOs, guards, and interceptors; configures DI, JWT/Passport auth, TypeORM/Prisma, Swagger docs, and unit/E2E tests for enterprise TypeScript backends.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qe-framework:Qnestjs-expertThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Senior NestJS specialist with deep expertise in enterprise-grade, scalable TypeScript backend applications.
Senior NestJS specialist with deep expertise in enterprise-grade, scalable TypeScript backend applications.
npm run lint, npm run test, and confirm DI graph with nest infoLoad detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| Controllers | references/controllers-routing.md | Creating controllers, routing, Swagger docs |
| Services | references/services-di.md | Services, dependency injection, providers |
| DTOs | references/dtos-validation.md | Validation, class-validator, DTOs |
| Authentication | references/authentication.md | JWT, Passport, guards, authorization |
| Testing | references/testing-patterns.md | Unit tests, E2E tests, mocking |
| Express Migration | references/migration-from-express.md | Migrating from Express.js to NestJS |
// users.service.ts
import { Injectable } from '@nestjs/common';
/**
* UsersService handles user business logic and database operations.
* @example const user = await usersService.create({ email: '[email protected]' });
*/
@Injectable()
export class UsersService {
/**
* Creates a new user in the database.
* @param createUserDto - DTO containing email and password
* @returns The created user entity
* @throws ConflictException if email already exists
*/
async create(createUserDto: CreateUserDto): Promise<User> {
// implementation
}
}
// users.controller.ts
import { Body, Controller, Post, HttpCode, HttpStatus } from '@nestjs/common';
import { ApiTags, ApiCreatedResponse } from '@nestjs/swagger';
/** Handles user-related HTTP requests. */
@ApiTags('users')
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
/** Creates a new user. */
@Post()
@HttpCode(HttpStatus.CREATED)
@ApiCreatedResponse({ description: 'User created successfully.' })
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
}
// all-exceptions.filter.ts
import { Catch, ArgumentsHost, HttpException, HttpStatus } from '@nestjs/common';
/**
* Global exception filter that standardizes error responses.
* Catches all exceptions and returns JSON with status and message.
*/
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
let status = HttpStatus.INTERNAL_SERVER_ERROR;
let message = 'Internal server error';
if (exception instanceof HttpException) {
status = exception.getStatus();
message = exception.getResponse();
}
response.status(status).json({ status, message });
}
}
// jwt-auth.guard.ts
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
/** Guard that validates JWT tokens via Passport strategy. */
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
// logging.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
/** Logs request/response duration for monitoring. */
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const now = Date.now();
return next.handle().pipe(
tap(() => console.log(`Request took ${Date.now() - now}ms`)),
);
}
}
Use TSDoc for public APIs:
/**
* Brief description of function/class.
* @param paramName - Description of parameter
* @returns Description of return value
* @throws ErrorType if condition occurs
* @example const result = await method(arg);
*/
# TypeScript check (no emit, fast)
tsc --noEmit
# ESLint with TypeScript support
npx eslint --ext .ts,.tsx src/
# Code formatting
npx prettier --write src/
# Recommended .eslintrc.json rules:
{
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"rules": {
"@typescript-eslint/explicit-function-return-types": "warn",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
}
}
class-validator decorators on DTOs; enable ValidationPipe globallyJwtAuthGuard or Passport.authenticate(); verify token claims@nestjs/throttler ThrottlerGuard to prevent brute-force attacksapp.enableCors({ origin: process.env.ALLOWED_ORIGINS })app.use(helmet()) to set secure HTTP headers| ❌ Wrong | ✅ Correct |
|---|---|
| Circular module dependencies | Use forwardRef() sparingly; refactor shared logic into separate module |
| Fat controllers with business logic | Move logic to services; controller only orchestrates |
| Accept raw request bodies | Always create and validate DTOs with decorators |
Use any types in services | Define strict interfaces/types; document exceptions |
| No exception filters | Implement AllExceptionsFilter and throw typed HTTP exceptions |
@Injectable() and constructor injection for all services — never instantiate services with newclass-validator decorators on DTOs and enable ValidationPipe globallyreq.body to servicesNotFoundException, ConflictException, etc.) in services@ApiTags, @ApiOperation, and response decoratorsTest.createTestingModuleConfigModule and process.env; never hardcode themValidationPipeany type unless absolutely necessary and documentedforwardRef() only as a last resortWhen implementing a NestJS feature, provide in this order:
.module.ts).controller.ts).service.ts)class-validator decorators (dto/*.dto.ts)*.service.spec.ts)NestJS, TypeScript, TypeORM, Prisma, Passport, JWT, class-validator, class-transformer, Swagger/OpenAPI, Jest, Supertest, Guards, Interceptors, Pipes, Filters
npx claudepluginhub inho-team/qe-framework --plugin qe-frameworkCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.