Skip to content

How to Use NestJS Expert Skill in Claude Code for Backend Development

Purpose

This post demonstrates how to use the NestJS Expert skill in Claude Code to build enterprise-grade backend applications with NestJS.

Environment

  • Claude Code with claude-skills plugin
  • Node.js 18+
  • TypeScript
  • NestJS

The NestJS Expert Skill

The NestJS Expert skill helps you build modular NestJS applications with proper dependency injection, controllers, services, and authentication. When you need to create REST APIs, GraphQL services, or implement guards and interceptors, this skill provides senior-level guidance.

There are several key benefits:

  • Modular architecture with dependency injection
  • Proper DTOs with validation
  • Authentication and authorization patterns
  • Database integration with TypeORM or Prisma
  • Testing strategies for services and controllers

How to Invoke

You can trigger the NestJS Expert skill in several ways:

Terminal window
# Use natural language
"Create a NestJS module for user management with JWT authentication"
# Reference specific topics
"Use nestjs-expert to build a controller with Swagger decorators"
# Ask for patterns
"Show me NestJS dependency injection patterns for services"

Example 1: Creating a Module

When I needed to create a product catalog module, I used:

"Use nestjs-expert to create a products module with CRUD endpoints"

The skill generated:

products.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ProductController } from './products.controller';
import { ProductService } from './products.service';
import { Product } from './entities/product.entity';
@Module({
imports: [TypeOrmModule.forFeature([Product])],
controllers: [ProductController],
providers: [ProductService],
exports: [ProductService],
})
export class ProductsModule {}

The controller included proper Swagger decorators:

products.controller.ts
import { Controller, Get, Post, Body, Param, HttpStatus } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { ProductService } from './products.service';
import { CreateProductDto } from './dto/create-product.dto';
@ApiTags('products')
@Controller('products')
export class ProductController {
constructor(private readonly productService: ProductService) {}
@Get()
@ApiOperation({ summary: 'Get all products' })
@ApiResponse({ status: 200, description: 'Returns array of products' })
findAll() {
return this.productService.findAll();
}
@Post()
@ApiOperation({ summary: 'Create a new product' })
@ApiResponse({ status: 201, description: 'Product created successfully' })
create(@Body() createProductDto: CreateProductDto) {
return this.productService.create(createProductDto);
}
}

Example 2: DTOs with Validation

The skill created validated DTOs using class-validator:

create-product.dto.ts
import { IsString, IsNumber, IsNotEmpty, Min, Max } from 'class-validator';
export class CreateProductDto {
@IsString()
@IsNotEmpty()
name: string;
@IsString()
description: string;
@IsNumber()
@Min(0)
price: number;
@IsNumber()
@Min(0)
@Max(100)
stock: number;
}

This validation happens automatically when the DTO is used in a controller with @Body() decorator.

Example 3: Service with Error Handling

The service implements business logic with proper error handling:

products.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Product } from './entities/product.entity';
import { CreateProductDto } from './dto/create-product.dto';
@Injectable()
export class ProductService {
constructor(
@InjectRepository(Product)
private readonly productRepository: Repository<Product>,
) {}
findAll() {
return this.productRepository.find();
}
async findOne(id: number) {
const product = await this.productRepository.findOne({ where: { id } });
if (!product) {
throw new NotFoundException(`Product with ID ${id} not found`);
}
return product;
}
create(createProductDto: CreateProductDto) {
const product = this.productRepository.create(createProductDto);
return this.productRepository.save(product);
}
}

Common Patterns

The NestJS Expert skill provides several patterns I use regularly:

Dependency Injection

┌─────────────────┐
│ Module │
│ (products) │
└────────┬────────┘
├─► Controller ──► Service ──► Repository
│ (inject) (inject) (TypeORM)
└─► Exports Service

The module manages dependencies. Controllers request services through constructor injection. Services request repositories. This creates testable, modular code.

Guards for Authentication

When I needed JWT authentication:

jwt-auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class JwtAuthGuard implements CanActivate {
constructor(
private jwtService: JwtService,
private reflector: Reflector,
) {}
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const token = this.extractTokenFromHeader(request);
if (!token) {
return false;
}
try {
const payload = this.jwtService.verify(token);
request['user'] = payload;
} catch {
return false;
}
return true;
}
private extractTokenFromHeader(request: Request): string | undefined {
return request.headers['authorization']?.split(' ')[1];
}
}

Apply guards to controllers or specific routes:

@Controller('products')
@UseGuards(JwtAuthGuard)
export class ProductController {
// All routes protected
}

Interceptors for Logging

The skill showed me how to add logging with interceptors:

logging.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const now = Date.now();
return next.handle().pipe(
tap(() => {
const duration = Date.now() - now;
console.log(`${request.method} ${request.url} - ${duration}ms`);
}),
);
}
}

DO and DON’T

Based on my experience using the NestJS Expert skill:

DO

  • Use dependency injection for all services and repositories
  • Validate all inputs with class-validator DTOs
  • Document APIs with Swagger decorators
  • Write unit tests for services
  • Use environment variables for configuration
  • Implement proper error handling with HTTP exceptions
  • Keep controllers thin, services focused

DON’T

  • Expose passwords or secrets in responses
  • Trust user input without validation
  • Use any type unless absolutely necessary
  • Create circular dependencies between modules
  • Hardcode configuration values
  • Skip error handling in services
  • Put business logic in controllers

Testing Patterns

The skill provides testing patterns for services:

products.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { ProductService } from './products.service';
import { Product } from './entities/product.entity';
import { Repository } from 'typeorm';
describe('ProductService', () => {
let service: ProductService;
let repository: Repository<Product>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ProductService,
{
provide: getRepositoryToken(Product),
useValue: {
find: jest.fn(),
findOne: jest.fn(),
create: jest.fn(),
save: jest.fn(),
},
},
],
}).compile();
service = module.get<ProductService>(ProductService);
repository = module.get<Repository<Product>>(getRepositoryToken(Product));
});
it('should return an array of products', async () => {
const expectedProducts = [{ id: 1, name: 'Test Product' }];
jest.spyOn(repository, 'find').mockResolvedValue(expectedProducts as Product[]);
const products = await service.findAll();
expect(products).toEqual(expectedProducts);
expect(repository.find).toHaveBeenCalled();
});
});

The NestJS Expert skill works well with other skills:

  • fullstack-guardian: For frontend-backend integration
  • test-master: For comprehensive testing strategies
  • security-review: For authentication and security best practices
  • devops-engineer: For deployment and infrastructure patterns

When to Use

I use the NestJS Expert skill when:

  • Building new NestJS modules or features
  • Implementing authentication or authorization
  • Creating DTOs with validation
  • Setting up database integration with TypeORM or Prisma
  • Writing tests for services and controllers
  • Migrating from Express.js to NestJS

Summary

In this post, I showed how to use the NestJS Expert skill in Claude Code to build modular backend applications. The key point is that the skill provides enterprise-grade patterns for dependency injection, validation, authentication, and testing in NestJS.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments