nodejs-expert
ihiteshgupta/ClaudeSkills/skills/backend/nodejs-expert/SKILL.md
Expert in Node.js backend development with Express, NestJS, TypeScript, and best practices. Use for building scalable Node.js APIs and services.
Skill0 starsChanged 11 months ago
- Reads credentials
What's in it
- Node.js Backend Development Expert
- Purpose
- When to Use This Skill
- Express.js API Structure
- Express + TypeScript Example
- app.ts
- Controller
- Service Layer
- Middleware
- NestJS Example
- Module
- Controller
- Service
- Testing
Tools it asks for
- Read
- Write
- Edit
- Grep
- Glob
- Bash
---
name: nodejs-expert
description: Expert in Node.js backend development with Express, NestJS, TypeScript, and best practices. Use for building scalable Node.js APIs and services.
allowed-tools: Read, Write, Edit, Grep, Glob, Bash
---
# Node.js Backend Development Expert
## Purpose
Provide expert guidance on Node.js backend development including Express, NestJS, TypeScript, API design, database integration, and production best practices.
## When to Use This Skill
- Building REST APIs with Express or NestJS
- TypeScript backend development
- Database integration (PostgreSQL, MongoDB)
- Authentication and authorization
- Error handling and logging
- Testing Node.js applications
- Performance optimization
- Production deployment
## Express.js API Structure
```
src/
├── app.ts
├── server.ts
├── config/
│ ├── database.ts
│ └── environment.ts
├── middleware/
│ ├── auth.ts
│ ├── errorHandler.ts
│ └── validation.ts
├── routes/
│ ├── index.ts
│ ├── users.ts
│ └── posts.ts
├── controllers/
│ ├── users.controller.ts
│ └── posts.controller.ts
├── services/
│ ├── users.service.ts
│ └── posts.service.ts
├── models/
│ ├── user.model.ts
│ └── post.model.ts
├── utils/
│ ├── logger.ts
│ └── validation.ts
└── types/
└── express.d.ts
```
## Express + TypeScript Example
### app.ts
```typescript
import express, { Express } from 'express';
import helmet from 'helmet';
import cors from 'cors';
import compression from 'compression';
import { errorHandler } from './middleware/errorHandler';
import { requestLogger } from './middleware/logger';
import routes from './routes';
export function createApp(): Express {
const app = express();
// Security
app.use(helmet());
app.use(cors({
origin: process.env.ALLOWED_ORIGINS?.split(','),
credentials: true
}));
// Parsing
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
app.use(compression());
// Logging
app.use(requestLogger);
// Routes
app.use('/api/v1', routes);
// Health check
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Error handling
app.use(errorHandler);
return app;
}
```
### Controller
```typescript
import { Request, Response, NextFunction } from 'express';
import { UserService } from '../services/users.service';
import { CreateUserDto, UpdateUserDto } from '../dto/user.dto';
import { validate } from '../utils/validation';
import { AppError } from '../utils/errors';
export class UserController {
constructor(private userService: UserService) {}
async create(req: Request, res: Response, next: NextFunction) {
try {
const dto = await validate(CreateUserDto, req.body);
const user = await this.userService.create(dto);
res.status(201).json({
success: true,
data: user
});
} catch (error) {
next(error);
}
}
async getById(req: Request, res: Response, next: NextFunction) {
try {
const { id } = req.params;
const user = await this.userService.findById(id);
if (!user) {
throw new AppError('User not found', 404);
}
res.json({
success: true,
data: user
});
} catch (error) {
next(error);
}
}
async update(req: Request, res: Response, next: NextFunction) {
try {
const { id } = req.params;
const dto = await validate(UpdateUserDto, req.body);
const user = await this.userService.update(id, dto);
res.json({
success: true,
data: user
});
} catch (error) {
next(error);
}
}
async delete(req: Request, res: Response, next: NextFunction) {
try {
const { id } = req.params;
await this.userService.delete(id);
res.status(204).send();
} catch (error) {
next(error);
}
}
}
```
### Service Layer
```typescript
import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcrypt';
import { CreateUserDto, UpdateUserDto } from '../dto/user.dto';
import { AppError } from '../utils/errors';
export class UserService {
constructor(private prisma: PrismaClient) {}
async create(dto: CreateUserDto) {
const existing = await this.prisma.user.findUnique({
where: { email: dto.email }
});
if (existing) {
throw new AppError('Email already exists', 409);
}
const hashedPassword = await bcrypt.hash(dto.password, 10);
return this.prisma.user.create({
data: {
...dto,
password: hashedPassword
},
select: {
id: true,
email: true,
name: true,
createdAt: true
}
});
}
async findById(id: string) {
return this.prisma.user.findUnique({
where: { id },
select: {
id: true,
email: true,
name: true,
createdAt: true
}
});
}
async update(id: string, dto: UpdateUserDto) {
return this.prisma.user.update({
where: { id },
data: dto,
select: {
id: true,
email: true,
name: true,
updatedAt: true
}
});
}
async delete(id: string) {
await this.prisma.user.delete({
where: { id }
});
}
}
```
### Middleware
```typescript
// Authentication
import jwt from 'jsonwebtoken';
import { Request, Response, NextFunction } from 'express';
import { AppError } from '../utils/errors';
interface JWTPayload {
userId: string;
email: string;
}
export async function authenticate(
req: Request,
res: Response,
next: NextFunction
) {
try {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
throw new AppError('No token provided', 401);
}
const payload = jwt.verify(
token,
process.env.JWT_SECRET!
) as JWTPayload;
req.user = payload;
next();
} catch (error) {
next(new AppError('Invalid token', 401));
}
}
// Error Handler
export function errorHandler(
err: Error,
req: Request,
res: Response,
next: NextFunction
) {
if (err instanceof AppError) {
return res.status(err.statusCode).json({
success: false,
error: {
message: err.message,
code: err.code
}
});
}
console.error('Unexpected error:', err);
res.status(500).json({
success: false,
error: {
message: 'Internal server error'
}
});
}
```
## NestJS Example
### Module
```typescript
import { Module } from '@nestjs/common';
import { UserController } from './users.controller';
import { UserService } from './users.service';
import { PrismaService } from '../prisma/prisma.service';
@Module({
controllers: [UserController],
providers: [UserService, PrismaService],
exports: [UserService]
})
export class UsersModule {}
```
### Controller
```typescript
import {
Controller,
Get,
Post,
Put,
Delete,
Body,
Param,
UseGuards,
HttpCode,
HttpStatus
} from '@nestjs/common';
import { UserService } from './users.service';
import { CreateUserDto, UpdateUserDto } from './dto/user.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { CurrentUser } from '../auth/decorators/current-user.decorator';
@Controller('users')
export class UserController {
constructor(private readonly userService: UserService) {}
@Post()
@HttpCode(HttpStatus.CREATED)
async create(@Body() createUserDto: CreateUserDto) {
return this.userService.create(createUserDto);
}
@Get(':id')
@UseGuards(JwtAuthGuard)
async findOne(@Param('id') id: string) {
return this.userService.findById(id);
}
@Put(':id')
@UseGuards(JwtAuthGuard)
async update(
@Param('id') id: string,
@Body() updateUserDto: UpdateUserDto
) {
return this.userService.update(id, updateUserDto);
}
@Delete(':id')
@UseGuards(JwtAuthGuard)
@HttpCode(HttpStatus.NO_CONTENT)
async remove(@Param('id') id: string) {
return this.userService.delete(id);
}
}
```
### Service
```typescript
import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CreateUserDto, UpdateUserDto } from './dto/user.dto';
@Injectable()
export class UserService {
constructor(private prisma: PrismaService) {}
async create(createUserDto: CreateUserDto) {
return this.prisma.user.create({
data: createUserDto
});
}
async findById(id: string) {
const user = await this.prisma.user.findUnique({
where: { id }
});
if (!user) {
throw new NotFoundException(`User with ID ${id} not found`);
}
return user;
}
async update(id: string, updateUserDto: UpdateUserDto) {
await this.findById(id);
return this.prisma.user.update({
where: { id },
data: updateUserDto
});
}
async delete(id: string) {
await this.findById(id);
await this.prisma.user.delete({
where: { id }
});
}
}
```
## Testing
```typescript
import request from 'supertest';
import { createApp } from '../app';
describe('User API', () => {
let app: Express;
beforeAll(() => {
app = createApp();
});
describe('POST /api/v1/users', () => {
it('should create a new user', async () => {
const response = await request(app)
.post('/api/v1/users')
.send({
email: 'test@example.com',
password: 'password123',
name: 'Test User'
});
expect(response.status).toBe(201);
expect(response.body.success).toBe(true);
expect(response.body.data.email).toBe('test@example.com');
});
});
});
```
This skill ensures production-ready, scalable Node.js applications.
More agent context in ihiteshgupta/ClaudeSkills
13 other files this repository gives its agents.
Skill
- system-designskills/architecture/system-design/SKILL.md
- codex-coderskills/codex-coder/SKILL.md
- terraformskills/devops/terraform/SKILL.md
- mermaid-diagramsskills/diagrams/mermaid-diagrams/SKILL.md
- technical-writerskills/documentation/technical-writer/SKILL.md
- css-expertskills/frontend/css-expert/SKILL.md
- react-expertskills/frontend/react-expert/SKILL.md
- vue-expertskills/frontend/vue-expert/SKILL.md
- kubernetes-expertskills/kubernetes/kubernetes-expert/SKILL.md
- android-expertskills/mobile/android-expert/SKILL.md
- ios-expertskills/mobile/ios-expert/SKILL.md
- security-expertskills/security/security-expert/SKILL.md
- ux-designerskills/ui-ux/ux-designer/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
Reports can't be read right now.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool public_context_discussion, action report. How to connect one.

