Skip to content

/ia-nodejs-backend

Node.js backend patterns: layered architecture, TypeScript, validation, error handling, security, observability, logging, metrics, deployment. Use when building REST APIs, REST endpoints, middleware, Express/Fastify/Hono/NestJS/Koa servers, tRPC procedures, Bun servers, or

From plugin
2831 skills12 commands
shell
$ npx -y skills add iliaal/whetstone --skill ia-nodejs-backend --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/ia-nodejs-backend
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Node.js backend patterns: layered architecture, TypeScript, validation, error handling, security, observability, logging, metrics, deployment. Use when building REST APIs, REST endpoints, middleware, Express/Fastify/Hono/NestJS/Koa servers, tRPC procedures, Bun servers, or

SKILL.md

ia-nodejs-backend.SKILL.md
name: ia-nodejs-backend
class: language
description: >-
  Node.js backend patterns: layered architecture, TypeScript, validation, error
  handling, security, observability, logging, metrics, deployment. Use when building REST APIs, REST endpoints, middleware,
  Express/Fastify/Hono/NestJS/Koa servers, tRPC procedures, Bun servers, or server-side TypeScript.
paths: "**/*.ts,**/*.js,**/*.mjs,**/*.cjs"

Node.js Backend

**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.

Framework Selection

| 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.

Architecture

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
  • Routes never contain business logic
  • Services never import Request/Response
  • Repositories never throw HTTP errors
  • Dependencies point inward only (Clean Architecture rule): routes -> services -> repositories. Never the reverse.
  • For scripts/prototypes: single file is fine -- ask "will this grow?"

TypeScript Rules

  • Use `import type { }` for type-only imports -- eliminates runtime overhead
  • Prefer `interface` for object shapes (2-5x faster type resolution than intersections)
  • Prefer `unknown` over `any` -- forces explicit narrowing
  • Use `z.infer<typeof Schema>` as single source of truth -- never duplicate types and schemas
  • Minimize `as` assertions -- use type guards instead
  • Add explicit return types to exported functions (faster declaration emit)
  • Untyped package? `declare module 'pkg' { const v: unknown; export default v; }` in `types/ambient.d.ts`

Validation

**Zod** (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.

Error Handling

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 statusCode
  • Unknown → log full stack, return 500 + generic message in production
  • Async wrapper: `const 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

API Design

**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.

  • **Hyrum's Law awareness**: every observable response field, ordering, or timing becomes a dependency for callers. Use Zod schemas or Fastify response schemas to control exactly what's serialized -- never return raw ORM objects or untyped objects from handlers.
  • **Addition over modification**: add new optional fields rather than changing or removing existing ones. Removing a field from a response schema breaks callers silently. Deprecate first (mark in OpenAPI spec), remove in a later version.
  • **Consistent error envelope**: all errors -- validation, auth, not-found, application -- must produce the same `{ error: { code, message, details? } }` structure. Centralize in the error handler middleware. Callers build error handling once; inconsistent errors force per-endpoint special cases.
  • **Boundary validation**: validate at the middleware/route handler level (Zod `.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.
  • **Third-party responses are untrusted data**: validate shape and content of external API responses before using them in logic, rendering, or decision-making. A compromised or misbehaving service can return unexpected types, malicious content, or missing fields. Parse through a Zod schema before use.
  • **Resources**: plural nouns (`/users`), max 2 nesting levels (`/users/:id/orders`)
  • **Methods**: GET read | POST create | PUT replace | PATCH partial | DELETE remove
  • **Versioning**: URL path `/api/v1/`
  • **Response**: `{ data, pagination?: { page, limit, total, totalPages } }`
  • **Queries**: `?page=1&limit=20&status=active&sort=createdAt,desc`
  • Return `Location` header on 201. Use 204 for successful DELETE with no body.

Async Patterns

| 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.

Production Resilience

  • **Fail-fast env validation**: parse and validate all environment variables at startup with a Zod schema (`const env = envSchema.parse(process.env)`). If invalid, crash before serving traffic. Never discover a missing env var on the first request t
Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withwhetstone

A Claude Code plugin that makes AI coding agents follow engineering discipline. Plan before coding. Verify before claiming done. Find root cause before patching. Review before merge. Skills activate based on file type and task signals, not manual toggling.

Get the whole plugin, auto-invoked
Stats
28
Stars
0
Views
2
Forks
Active
Maintenance
Python
Language
MIT
License
4d ago
Last commit
5mo ago
Created

Repo: iliaal/whetstone

Other skills on whetstone.