backend-nodejs
Node.js/TypeScript backend expert. Handles Express/Fastify API routes, TypeScript strict mode, Prisma ORM, Zod validation, error handling, configuration management. Use when project is Node.js backend (package.json + TypeScript server).
Best use case
backend-nodejs is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Node.js/TypeScript backend expert. Handles Express/Fastify API routes, TypeScript strict mode, Prisma ORM, Zod validation, error handling, configuration management. Use when project is Node.js backend (package.json + TypeScript server).
Teams using backend-nodejs should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/backend-nodejs-nera0875/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How backend-nodejs Compares
| Feature / Agent | backend-nodejs | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Node.js/TypeScript backend expert. Handles Express/Fastify API routes, TypeScript strict mode, Prisma ORM, Zod validation, error handling, configuration management. Use when project is Node.js backend (package.json + TypeScript server).
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Backend Node.js Skill - API Development Expert
> **Expert backend Node.js/TypeScript pour API REST + GraphQL**
>
> Inspiré de : Vercel API design, Stripe backend patterns, Prisma best practices
---
## Scope
**Chargé par:** executor agent (SI projet Node.js détecté)
**Détection auto:**
- Fichier `package.json` existe
- Fichiers `server.ts` ou `index.ts` ou `src/server.ts`
- Dependencies: `express`, `fastify`, `@prisma/client`, etc
**Stack supporté:**
- **Runtime:** Node.js 18+ / Bun
- **Language:** TypeScript (strict mode)
- **Frameworks:** Express, Fastify, Hono
- **Database:** Prisma ORM
- **Validation:** Zod
- **Testing:** Vitest, Jest
---
## Conventions Strictes
### 1. Structure Projet (Obligatoire)
```
backend/
├── src/
│ ├── config/
│ │ └── env.ts # Configuration centralisée (1 seul fichier)
│ ├── routes/
│ │ ├── index.ts # Router principal
│ │ ├── tasks.ts
│ │ └── users.ts
│ ├── services/
│ │ ├── task.service.ts # Business logic
│ │ └── user.service.ts
│ ├── middleware/
│ │ ├── auth.ts
│ │ ├── error.ts
│ │ └── validation.ts
│ ├── types/
│ │ └── index.ts # TypeScript types partagés
│ ├── lib/
│ │ ├── prisma.ts # Prisma client singleton
│ │ └── logger.ts
│ └── server.ts # Entry point
├── prisma/
│ └── schema.prisma
├── package.json
├── tsconfig.json
└── .env
```
---
### 2. Configuration (1 seul fichier - 12-Factor App)
```typescript
// src/config/env.ts
import { z } from 'zod'
const envSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
PORT: z.string().default('3000'),
DATABASE_URL: z.string(),
JWT_SECRET: z.string().min(32),
CORS_ORIGIN: z.string().default('http://localhost:3000'),
LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
})
export const env = envSchema.parse(process.env)
export type Env = z.infer<typeof envSchema>
```
**Principe:** Validation config au démarrage, crash immédiat si config invalide.
---
### 3. Prisma Client Singleton (Pattern Vercel)
```typescript
// src/lib/prisma.ts
import { PrismaClient } from '@prisma/client'
import { env } from '@/config/env'
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}
export const prisma =
globalForPrisma.prisma ??
new PrismaClient({
log: env.NODE_ENV === 'development'
? ['query', 'error', 'warn']
: ['error'],
})
if (env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma
}
```
**Interdiction:** Créer plusieurs instances PrismaClient (épuise connexions DB).
---
### 4. Routes Pattern (Express)
```typescript
// src/routes/tasks.ts
import { Router } from 'express'
import { z } from 'zod'
import { taskService } from '@/services/task.service'
import { validateRequest } from '@/middleware/validation'
import { requireAuth } from '@/middleware/auth'
const router = Router()
// Zod schemas
const createTaskSchema = z.object({
body: z.object({
title: z.string().min(1).max(200),
description: z.string().optional(),
status: z.enum(['PENDING', 'IN_PROGRESS', 'COMPLETED']).default('PENDING'),
}),
})
// Routes
router.post(
'/',
requireAuth,
validateRequest(createTaskSchema),
async (req, res, next) => {
try {
const task = await taskService.createTask(req.user.id, req.body)
res.status(201).json(task)
} catch (error) {
next(error)
}
}
)
router.get(
'/',
requireAuth,
async (req, res, next) => {
try {
const tasks = await taskService.getTasks(req.user.id)
res.json(tasks)
} catch (error) {
next(error)
}
}
)
router.patch(
'/:id',
requireAuth,
validateRequest(z.object({
params: z.object({ id: z.string().cuid() }),
body: createTaskSchema.shape.body.partial(),
})),
async (req, res, next) => {
try {
const task = await taskService.updateTask(
req.params.id,
req.user.id,
req.body
)
res.json(task)
} catch (error) {
next(error)
}
}
)
export default router
```
**Pattern:** Routes légères → Business logic dans services.
---
### 5. Services Pattern (Singleton + Business Logic)
```typescript
// src/services/task.service.ts
import { prisma } from '@/lib/prisma'
import { TaskStatus } from '@prisma/client'
export class TaskService {
async createTask(
userId: string,
data: { title: string; description?: string; status?: TaskStatus }
) {
// Business logic validation
const existingCount = await prisma.task.count({
where: { userId, status: 'PENDING' },
})
if (existingCount >= 100) {
throw new Error('Maximum pending tasks limit reached')
}
// Create with transaction if multiple operations
return prisma.task.create({
data: {
...data,
userId,
},
include: {
user: {
select: { id: true, name: true, email: true },
},
},
})
}
async getTasks(userId: string) {
return prisma.task.findMany({
where: { userId },
include: {
user: {
select: { id: true, name: true },
},
},
orderBy: { createdAt: 'desc' },
})
}
async updateTask(
id: string,
userId: string,
data: Partial<{ title: string; description?: string; status?: TaskStatus }>
) {
// Check ownership
const task = await prisma.task.findUnique({
where: { id },
select: { userId: true },
})
if (!task || task.userId !== userId) {
throw new Error('Task not found or access denied')
}
return prisma.task.update({
where: { id },
data,
})
}
async deleteTask(id: string, userId: string) {
// Check ownership
const task = await prisma.task.findUnique({
where: { id },
select: { userId: true },
})
if (!task || task.userId !== userId) {
throw new Error('Task not found or access denied')
}
return prisma.task.delete({
where: { id },
})
}
}
// Singleton export
export const taskService = new TaskService()
```
**Principe:** 1 service = 1 ressource, toute business logic centralisée.
---
### 6. Error Handling Middleware (Standardisé)
```typescript
// src/middleware/error.ts
import { Request, Response, NextFunction } from 'express'
import { ZodError } from 'zod'
import { Prisma } from '@prisma/client'
import { logger } from '@/lib/logger'
export class AppError extends Error {
constructor(
message: string,
public statusCode: number = 500,
public type: string = 'server_error'
) {
super(message)
}
}
export function errorHandler(
error: Error,
req: Request,
res: Response,
next: NextFunction
) {
// Zod validation error
if (error instanceof ZodError) {
return res.status(400).json({
message: 'Validation error',
type: 'validation_error',
errors: error.errors.map(e => ({
path: e.path.join('.'),
message: e.message,
})),
})
}
// Prisma errors
if (error instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2002') {
return res.status(409).json({
message: 'Resource already exists',
type: 'conflict_error',
})
}
if (error.code === 'P2025') {
return res.status(404).json({
message: 'Resource not found',
type: 'not_found_error',
})
}
}
// App errors (custom)
if (error instanceof AppError) {
return res.status(error.statusCode).json({
message: error.message,
type: error.type,
})
}
// Unknown errors
logger.error('Unexpected error:', error)
return res.status(500).json({
message: 'Internal server error',
type: 'server_error',
})
}
```
---
### 7. Validation Middleware (Zod)
```typescript
// src/middleware/validation.ts
import { Request, Response, NextFunction } from 'express'
import { AnyZodObject, ZodError } from 'zod'
export function validateRequest(schema: AnyZodObject) {
return async (req: Request, res: Response, next: NextFunction) => {
try {
await schema.parseAsync({
body: req.body,
query: req.query,
params: req.params,
})
next()
} catch (error) {
if (error instanceof ZodError) {
return res.status(400).json({
message: 'Validation error',
type: 'validation_error',
errors: error.errors.map(e => ({
path: e.path.join('.'),
message: e.message,
})),
})
}
next(error)
}
}
}
```
---
### 8. Server Entry Point
```typescript
// src/server.ts
import express from 'express'
import cors from 'cors'
import helmet from 'helmet'
import { env } from '@/config/env'
import { errorHandler } from '@/middleware/error'
import { logger } from '@/lib/logger'
import router from '@/routes'
const app = express()
// Security middleware
app.use(helmet())
app.use(cors({ origin: env.CORS_ORIGIN }))
app.use(express.json({ limit: '10mb' }))
// Health check
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() })
})
// API routes
app.use('/api', router)
// Error handler (MUST be last)
app.use(errorHandler)
// Start server
const server = app.listen(env.PORT, () => {
logger.info(`Server running on port ${env.PORT}`)
logger.info(`Environment: ${env.NODE_ENV}`)
})
// Graceful shutdown
process.on('SIGTERM', () => {
logger.info('SIGTERM received, shutting down gracefully')
server.close(() => {
logger.info('Server closed')
process.exit(0)
})
})
export default app
```
---
### 9. TypeScript Config (Strict Mode)
```json
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
```
---
## Naming Conventions
### Variables & Functions (camelCase)
```typescript
const userId = "123"
const currentUser = await getUser()
async function createTask() {}
async function getUserTasks() {}
```
### Classes & Types (PascalCase)
```typescript
class TaskService {}
type TaskResponse = {}
interface UserData {}
```
### Files (kebab-case)
```
task.service.ts
user.controller.ts
auth.middleware.ts
```
### Constants (SCREAMING_SNAKE_CASE)
```typescript
const MAX_TASKS_PER_USER = 100
const DEFAULT_PAGE_SIZE = 20
```
---
## Anti-Patterns à Éviter
❌ **Multiple PrismaClient instances**
```typescript
// ❌ INTERDIT
const prisma = new PrismaClient() // Dans chaque fichier
```
✅ **Singleton pattern**
```typescript
// ✅ CORRECT
import { prisma } from '@/lib/prisma'
```
---
❌ **Business logic dans routes**
```typescript
// ❌ INTERDIT
router.post('/', async (req, res) => {
const task = await prisma.task.create({ data: req.body })
res.json(task)
})
```
✅ **Business logic dans services**
```typescript
// ✅ CORRECT
router.post('/', async (req, res) => {
const task = await taskService.createTask(req.user.id, req.body)
res.json(task)
})
```
---
❌ **Pas de validation**
```typescript
// ❌ INTERDIT
router.post('/', async (req, res) => {
const task = await taskService.createTask(req.body) // Pas de validation
})
```
✅ **Zod validation middleware**
```typescript
// ✅ CORRECT
router.post('/', validateRequest(createTaskSchema), async (req, res) => {
const task = await taskService.createTask(req.body)
})
```
---
❌ **Errors non catchés**
```typescript
// ❌ INTERDIT
router.get('/', async (req, res) => {
const tasks = await taskService.getTasks() // Crash si erreur
})
```
✅ **Try/catch + next(error)**
```typescript
// ✅ CORRECT
router.get('/', async (req, res, next) => {
try {
const tasks = await taskService.getTasks()
res.json(tasks)
} catch (error) {
next(error) // Error handler middleware
}
})
```
---
## Checklist Feature API
**Avant créer route:**
- [ ] Service existe? (anti-duplication)
- [ ] Zod schema défini?
- [ ] Auth middleware si protected?
- [ ] Error handling (try/catch + next)?
**Après créer route:**
- [ ] Route exportée dans `routes/index.ts`?
- [ ] Types TypeScript définis?
- [ ] Ownership checks (si user data)?
---
## Exemples Complets
### Exemple 1: CRUD Tasks API
**Structure créée:**
```
src/
├── routes/tasks.ts # Routes HTTP
├── services/task.service.ts # Business logic
├── types/task.ts # TypeScript types
```
**Workflow:**
1. Zod schema validation
2. Route appelle service
3. Service utilise Prisma
4. Error handling middleware
---
### Exemple 2: Auth Middleware
```typescript
// src/middleware/auth.ts
import { Request, Response, NextFunction } from 'express'
import jwt from 'jsonwebtoken'
import { env } from '@/config/env'
import { AppError } from '@/middleware/error'
declare global {
namespace Express {
interface Request {
user: { id: string; email: string }
}
}
}
export async function requireAuth(
req: Request,
res: Response,
next: NextFunction
) {
try {
const token = req.headers.authorization?.replace('Bearer ', '')
if (!token) {
throw new AppError('Authentication required', 401, 'auth_error')
}
const decoded = jwt.verify(token, env.JWT_SECRET) as {
id: string
email: string
}
req.user = decoded
next()
} catch (error) {
if (error instanceof jwt.JsonWebTokenError) {
return next(new AppError('Invalid token', 401, 'auth_error'))
}
next(error)
}
}
```
---
## Workflow Executor avec Backend-Node Skill
**Détection auto:**
```
1. executor scan projet
2. Trouve package.json + src/server.ts
3. Load backend-nodejs skill (au lieu de backend Python)
4. Applique conventions Node.js/TypeScript
```
**Feature création:**
```
User: "Crée CRUD tasks API"
executor:
1. Load skills: backend-nodejs + frontend + integration
2. Crée structure selon conventions Node.js
3. Zod validation + Prisma + Express routes
4. Services singleton pattern
5. Error handling standardisé
```
---
## Principes
1. **TypeScript Strict Mode** - Zéro `any`, types partout
2. **Configuration Centralisée** - 1 seul `env.ts` (12-Factor App)
3. **Services Singleton** - 1 service par ressource, réutilisable
4. **Validation Zod** - Toutes inputs validées
5. **Error Handling Standardisé** - Errors structurés + types
6. **Prisma Best Practices** - Singleton client, select optimization
7. **Separation of Concerns** - Routes → Services → Prisma
**Inspiré de:**
- Vercel API Routes design
- Stripe backend architecture (services pattern)
- Prisma documentation (singleton, transactions)
- Express.js best practices
---
**Version**: 1.0.0
**Created**: 2025-01-10
**Maintained by**: executor agent (loaded si projet Node.js détecté)Related Skills
backend-patterns
Backend patterns for ORPC routers, Drizzle schemas, and server-side code. Use when creating API endpoints, database tables, or services.
backend-passport-js
Authentication middleware for Express.js and Node.js applications. Use when building Express APIs that need JWT authentication, OAuth, or custom auth strategies. Provides 500+ authentication strategies. Choose Passport.js over Auth.js for Express backends, pure API servers, or when you need maximum control over auth flow.
Backend Node.js Expert
专注于 Node.js 后端开发模式与最佳实践。
Backend Migrations
Create and manage database schema migrations with reversible operations, zero-downtime deployments, and safe rollback strategies. Use this skill when writing database migrations for PostgreSQL, MySQL, SQLite, MongoDB, or any database system; when using ORMs like Prisma, Sequelize, TypeORM, ActiveRecord, Django ORM, or similar migration tools; when implementing schema changes (adding tables, columns, indexes, constraints); when performing data migrations or transformations; when creating indexes on large tables with concurrent options to avoid locks; when separating schema changes from data migrations for safer rollbacks; when implementing zero-downtime deployment strategies for high-availability systems; when versioning database schemas and managing migration order; or when working with database change management in production environments.
backend
Skill para diseñar y construir backends y APIs **modulares**, **auditables**, **resilientes** y **multi-tenant**, con seguridad fuerte, modelado correcto (incl. ledger cuando aplique), datos y jobs/colas operables.
backend-guidelines
Comprehensive backend development guide for Node.js/Express/TypeScript microservices. Use when creating routes, controllers, services, repositories, middleware, or working with Express APIs, Prisma database access, Sentry error tracking, Zod validation, unifiedConfig, dependency injection, or async patterns. Covers layered architecture (routes → controllers → services → repositories), BaseController pattern, error handling, performance monitoring, testing strategies, and migration from legacy patterns.
backend-guide
Complete backend development guide covering Node.js, Python, Go, Java, PHP, databases, APIs, authentication, and server architecture. Use when building server applications, APIs, or backend systems.
Backend Expert Pro
A complete back-end specialist skill for designing scalable architectures, robust APIs, and secure server-side systems.
backend-expert-advisor
Backend expert guidance for API/DB/Security/Architecture
backend-development
Build robust backend systems with modern technologies (Node.js, Python, Go, Rust), frameworks (NestJS, FastAPI, Django), databases (PostgreSQL, MongoDB, Redis), APIs (REST, GraphQL, gRPC), authentication (OAuth 2.1, JWT), testing strategies, security best practices (OWASP Top 10), performance optimization, scalability patterns (microservices, caching, sharding), DevOps practices (Docker, Kubernetes, CI/CD), and monitoring. Use when designing APIs, implementing authentication, optimizing database queries, setting up CI/CD pipelines, handling security vulnerabilities, building microservices, or developing production-ready backend systems.
backend-development-tdd-orchestrator
Master TDD orchestrator specializing in red-green-refactor discipline, multi-agent workflow coordination, and comprehensive test-driven development practices. Enforces TDD best practices across teams with AI-assisted testing and modern frameworks. Use PROACTIVELY for TDD implementation and governance. Use when: the task directly matches tdd orchestrator responsibilities within plugin backend-development. Do not use when: a more specific framework or task-focused skill is clearly a better match.
backend-development-graphql-architect
Master modern GraphQL with federation, performance optimization, and enterprise security. Build scalable schemas, implement advanced caching, and design real-time systems. Use PROACTIVELY for GraphQL architecture or performance optimization. Use when: the task directly matches graphql architect responsibilities within plugin backend-development. Do not use when: a more specific framework or task-focused skill is clearly a better match.