skills/nodejs-backend/SKILL.md
Node.js backend patterns: layered architecture, TypeScript, validation, error handling, security, deployment. Use when building REST APIs, REST endpoints, middleware, Express/Fastify/Hono/NestJS/Koa servers, tRPC procedures, Bun servers, or server-side TypeScript.
npx skillsauth add iliaal/ai-skills nodejs-backendInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Verify before implementing: For framework-specific APIs (Express 5, Fastify 5, Node.js 22+ built-ins), look up current docs via Context7 (query-docs) before writing code. Training data may lag current releases.
| Context | Choose | Why | |---------|--------|-----| | Edge/Serverless | Hono | Zero-dep, fastest cold starts | | Performance API | Fastify | Higher throughput than Express, built-in schema validation | | Enterprise/team | NestJS | DI, decorators, structured conventions | | Legacy/ecosystem | Express | Most middleware, widest adoption |
Ask user: deployment target, cold start needs, team experience, existing codebase.
src/
├── routes/ # HTTP: parse request, call service, format response
├── middleware/ # Auth, validation, rate limiting, logging
├── services/ # Business logic (no HTTP types)
├── repositories/ # Data access only (queries, ORM)
├── config/ # Env, DB pool, constants
└── types/ # Shared TypeScript interfaces
import type { } for type-only imports -- eliminates runtime overheadinterface for object shapes (2-5x faster type resolution than intersections)unknown over any -- forces explicit narrowingz.infer<typeof Schema> as single source of truth -- never duplicate types and schemasas assertions -- use type guards insteaddeclare module 'pkg' { const v: unknown; export default v; } in types/ambient.d.tsZod (TypeScript inference) or TypeBox (Fastify native). Validate at boundaries only: request entry, before DB ops, env vars at startup. Use .extend(), .pick(), .omit(), .partial(), .merge() for DRY schemas.
Custom error hierarchy: AppError(message, statusCode, isOperational) → ValidationError(400), NotFoundError(404), UnauthorizedError(401), ForbiddenError(403), ConflictError(409)
Centralized handler middleware:
AppError → return { error: message } with statusCodeconst asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);Codes: 400 bad input | 401 no auth | 403 no permission | 404 missing | 409 conflict | 422 business rule | 429 rate limited | 500 server fault
Contract-first: define route schemas (Zod schemas, Fastify JSON Schema, or OpenAPI spec) before writing handler logic. The schema is the contract -- implementation follows. Generate OpenAPI/Swagger docs from these schemas for interactive API documentation.
{ error: { code, message, details? } } structure. Centralize in the error handler middleware. Callers build error handling once; inconsistent errors force per-endpoint special cases..parse() on request body/params, Fastify schema validation). Services and repositories trust that input was validated at entry -- no redundant checks scattered through business logic./users), max 2 nesting levels (/users/:id/orders)/api/v1/{ data, pagination?: { page, limit, total, totalPages } }?page=1&limit=20&status=active&sort=createdAt,descLocation header on 201. Use 204 for successful DELETE with no body.| Pattern | Use When |
|---------|----------|
| async/await | Sequential operations |
| Promise.all | Parallel independent ops |
| Promise.allSettled | Parallel, some may fail |
| Promise.race | Timeout or first-wins |
Never use readFileSync or other sync methods in production -- use fs.promises or stream equivalents. Offload CPU work to worker threads (Piscina). Stream large payloads.
const env = envSchema.parse(process.env)). If invalid, crash before serving traffic. Never discover a missing env var on the first request that needs it./health (shallow, always 200 if process is alive) and /ready (deep, verifies database, cache, and critical dependencies are reachable). Load balancers probe /ready for traffic routing; monitoring probes /health for process liveness. Don't conflate them.@fastify/under-pressure (or equivalent) -- monitor event loop delay, heap, RSS; return 503 when thresholds exceeded.fast-json-stringify for 2-3x faster serialization.opossum for outbound service calls. States: CLOSED (normal) -> OPEN (failing, return fallback) -> HALF_OPEN (probe). Prevents cascade failures when downstream services are down.as any, non-null assertions on untrusted data, // @ts-ignore), treat it as a design smell and find the typed solutiontsc --noEmit && npm test pass with zero warnings before declaring donetsc --noEmit passes with zero errorsnpm test passes with zero failuresas any, @ts-ignore) in new codetools
Tailwind CSS v4 patterns: CSS-first config, utility classes, component variants, v3 migration. Use when styling with Tailwind, configuring @theme tokens, using tailwind-variants/CVA, migrating v3 to v4, or fixing Tailwind styles and dark mode.
development
Simplifies, polishes, and declutters code without changing behavior. Use when asked to simplify, clean up, refactor, declutter, remove dead code or AI slop, or improve readability. For analysis-only reports without code changes, use code-simplicity-reviewer agent.
development
React architecture patterns, TypeScript, Next.js, hooks, and testing. Use when working with React component structure, state management, Next.js routing, Vitest, React Testing Library, or reviewing React code. For visual design and aesthetic direction, use frontend-design instead.
development
Pine Script v6: syntax, performance, error diagnosis, backtesting, visualization. Use when writing or debugging `.pine` files or TradingView Pine indicators/strategies.