Non-negotiable rules:
- Read
references/stack.md first to determine the runtime (Node.js or Bun), framework, and locked decisions.
- Then load only the references needed for the actual task.
- TypeScript strict mode — no
any, no implicit returns, no unchecked index access.
- All async functions must handle errors — no unhandled promise rejections. Use try/catch or
.catch() at every boundary.
- Input validation at system boundaries — Zod schemas on every external input (request bodies, query params, env vars, CLI args). Never trust
req.body.
- Structured logging via pino — no
console.log in production code. JSON to stdout, parsed by log aggregators.
- Graceful shutdown — handle SIGTERM/SIGINT, drain connections, finish in-flight work, close DB pools.
- No secrets in code or logs — env vars validated at startup, never logged, never in error responses.
nodejs
Inputs
$request: The backend task, subsystem, bug, or feature being worked on
Goal
Route Node.js/Bun backend work through the project's conventions so implementation follows the established patterns for server architecture, data access, error handling, and deployment.
Step 0: Read the stack contract
Always start with:
That establishes: runtime (Node.js or Bun), framework (Express/Fastify/Hono/none), ORM, test runner, package manager, and locked dependency choices.
If bun.lockb or bunfig.toml exists, the runtime is Bun — also load references/bun-runtime.md for native API differences.
Success criteria: The project's runtime, framework, and toolchain choices are explicit before implementation starts.
Step 1: Load only the relevant references
Use the routing table to pick reference files. Do not bulk-load the full reference tree.
| Task |
Read |
| Runtime, TypeScript, package manager, locked deps |
references/stack.md |
| Folder conventions, entry points, monorepo layout |
references/project-structure.md |
| Express/Fastify/Hono patterns, middleware, routing |
references/http-server.md |
| REST conventions, versioning, pagination, error responses |
references/api-design.md |
| Zod/AJV input validation, DTO patterns |
references/validation.md |
| Prisma/Drizzle/Knex, migrations, connection pooling |
references/database.md |
| JWT, sessions, OAuth2, RBAC, middleware guards |
references/auth.md |
| Error classes, async error boundaries, HTTP error responses |
references/error-handling.md |
| pino structured logging, request correlation, log levels |
references/logging.md |
| vitest/jest/bun test, supertest, test factories, coverage |
references/testing.md |
| Promises, streams, worker threads, AbortController, shutdown |
references/async-patterns.md |
| helmet, CORS, rate limiting, input sanitization, dep audit |
references/security.md |
| Redis, in-memory caching, cache invalidation patterns |
references/caching.md |
| BullMQ, job patterns, retry strategies, dead-letter queues |
references/queues-jobs.md |
| Env validation, dotenv, config modules, secrets management |
references/config.md |
| OpenTelemetry, health checks, metrics, distributed tracing |
references/observability.md |
| Multi-stage Dockerfile, .dockerignore, prod vs dev images |
references/docker.md |
| ws/Socket.io, connection lifecycle, scaling, rooms |
references/websockets.md |
| commander/yargs, argument parsing, exit codes, stdin/stdout |
references/cli.md |
| Bun-native APIs, bun test, bun build, Bun.serve, Bun.$ |
references/bun-runtime.md |
Multiple tasks? Read multiple files. The references are self-contained.
Success criteria: Only the task-relevant backend conventions are in play.
Step 2: Implement with the core backend guardrails
Keep these rules active:
- TypeScript strict mode with
noUncheckedIndexedAccess
- all external input validated at the boundary (Zod schemas)
- errors are typed, caught, and returned as structured HTTP responses
- logging via pino child loggers with request correlation IDs
- database access through the project's ORM/query builder, not raw SQL strings
- mutations wrapped in transactions where atomicity matters
- graceful shutdown: SIGTERM handler drains server, closes pools, exits cleanly
- env vars validated at startup — fail fast on missing required config
- no
any, no as type assertions unless justified with a comment
- if Bun runtime: prefer
Bun.serve(), Bun.file(), bun test over Node.js equivalents
Success criteria: The change matches the project's backend architecture instead of generic defaults.
Step 3: Verify the affected surface
Use the narrowest relevant verification:
- unit tests (
vitest run, jest, or bun test)
- integration tests with supertest or actual HTTP calls
- type checking (
tsc --noEmit)
- linting (
eslint .)
- if Docker: build the image and verify it starts
Success criteria: The changed backend surface still builds, type-checks, and passes tests.
Guardrails
- Do not inline the whole Node.js handbook in
SKILL.md.
- Do not skip
references/stack.md.
- Do not use
console.log in production code — use pino.
- Do not bypass input validation at API boundaries.
- Do not leave unhandled promise rejections.
- Do not hardcode secrets, ports, or environment-specific values.
- Do not add
disable-model-invocation; this is a normal domain skill.
When To Load References
references/stack.md
Always.
references/bun-runtime.md
When the project uses Bun (detected via bun.lockb or bunfig.toml).
then only the task-relevant files under references/
Output Contract
Report:
- which references were loaded
- the architecture pattern chosen
- the change made
- the verification run
1---2name: nodejs3description: Write Node.js and Bun backend code the way THIS project already does it, not by generic defaults — a TypeScript-first reference that detects the runtime and carries the real conventions for HTTP servers, Zod boundary validation, typed error handling, pino logging, database access, auth, BullMQ queues, caching, async and graceful-shutdown patterns, security, CLI tooling, testing, and observability, so a change lands idiomatic and review-ready instead of merely running. Use when a task touches this project's Node.js or Bun backend and should follow its conventions rather than generic defaults.4---5
6<EXTREMELY-IMPORTANT>
7This skill is a routing shell over the Node.js/Bun reference set.
8
9Non-negotiable rules:
101. Read `references/stack.md` first to determine the runtime (Node.js or Bun), framework, and locked decisions.
112. Then load only the references needed for the actual task.
123. **TypeScript strict mode** — no `any`, no implicit returns, no unchecked index access.
134. **All async functions must handle errors** — no unhandled promise rejections. Use try/catch or `.catch()` at every boundary.
145. **Input validation at system boundaries** — Zod schemas on every external input (request bodies, query params, env vars, CLI args). Never trust `req.body`.
156. **Structured logging via pino** — no `console.log` in production code. JSON to stdout, parsed by log aggregators.
167. **Graceful shutdown** — handle SIGTERM/SIGINT, drain connections, finish in-flight work, close DB pools.
178. **No secrets in code or logs** — env vars validated at startup, never logged, never in error responses.
18</EXTREMELY-IMPORTANT>
19
20# nodejs
21
22## Inputs
23
24- `$request`: The backend task, subsystem, bug, or feature being worked on
25
26## Goal
27
28Route Node.js/Bun backend work through the project's conventions so implementation follows the established patterns for server architecture, data access, error handling, and deployment.
29
30## Step 0: Read the stack contract
31
32Always start with:
33
34- `references/stack.md`
35
36That establishes: runtime (Node.js or Bun), framework (Express/Fastify/Hono/none), ORM, test runner, package manager, and locked dependency choices.
37
38If `bun.lockb` or `bunfig.toml` exists, the runtime is Bun — also load `references/bun-runtime.md` for native API differences.
39
40**Success criteria**: The project's runtime, framework, and toolchain choices are explicit before implementation starts.
41
42## Step 1: Load only the relevant references
43
44Use the routing table to pick reference files. Do not bulk-load the full reference tree.
45
46| Task | Read |
47|------|------|
48| Runtime, TypeScript, package manager, locked deps | `references/stack.md` |
49| Folder conventions, entry points, monorepo layout | `references/project-structure.md` |
50| Express/Fastify/Hono patterns, middleware, routing | `references/http-server.md` |
51| REST conventions, versioning, pagination, error responses | `references/api-design.md` |
52| Zod/AJV input validation, DTO patterns | `references/validation.md` |
53| Prisma/Drizzle/Knex, migrations, connection pooling | `references/database.md` |
54| JWT, sessions, OAuth2, RBAC, middleware guards | `references/auth.md` |
55| Error classes, async error boundaries, HTTP error responses | `references/error-handling.md` |
56| pino structured logging, request correlation, log levels | `references/logging.md` |
57| vitest/jest/bun test, supertest, test factories, coverage | `references/testing.md` |
58| Promises, streams, worker threads, AbortController, shutdown | `references/async-patterns.md` |
59| helmet, CORS, rate limiting, input sanitization, dep audit | `references/security.md` |
60| Redis, in-memory caching, cache invalidation patterns | `references/caching.md` |
61| BullMQ, job patterns, retry strategies, dead-letter queues | `references/queues-jobs.md` |
62| Env validation, dotenv, config modules, secrets management | `references/config.md` |
63| OpenTelemetry, health checks, metrics, distributed tracing | `references/observability.md` |
64| Multi-stage Dockerfile, .dockerignore, prod vs dev images | `references/docker.md` |
65| ws/Socket.io, connection lifecycle, scaling, rooms | `references/websockets.md` |
66| commander/yargs, argument parsing, exit codes, stdin/stdout | `references/cli.md` |
67| Bun-native APIs, bun test, bun build, Bun.serve, Bun.$ | `references/bun-runtime.md` |
68
69Multiple tasks? Read multiple files. The references are self-contained.
70
71**Success criteria**: Only the task-relevant backend conventions are in play.
72
73## Step 2: Implement with the core backend guardrails
74
75Keep these rules active:
76
77- TypeScript strict mode with `noUncheckedIndexedAccess`
78- all external input validated at the boundary (Zod schemas)
79- errors are typed, caught, and returned as structured HTTP responses
80- logging via pino child loggers with request correlation IDs
81- database access through the project's ORM/query builder, not raw SQL strings
82- mutations wrapped in transactions where atomicity matters
83- graceful shutdown: SIGTERM handler drains server, closes pools, exits cleanly
84- env vars validated at startup — fail fast on missing required config
85- no `any`, no `as` type assertions unless justified with a comment
86- if Bun runtime: prefer `Bun.serve()`, `Bun.file()`, `bun test` over Node.js equivalents
87
88**Success criteria**: The change matches the project's backend architecture instead of generic defaults.
89
90## Step 3: Verify the affected surface
91
92Use the narrowest relevant verification:
93
94- unit tests (`vitest run`, `jest`, or `bun test`)
95- integration tests with supertest or actual HTTP calls
96- type checking (`tsc --noEmit`)
97- linting (`eslint .`)
98- if Docker: build the image and verify it starts
99
100**Success criteria**: The changed backend surface still builds, type-checks, and passes tests.
101
102## Guardrails
103
104- Do not inline the whole Node.js handbook in `SKILL.md`.
105- Do not skip `references/stack.md`.
106- Do not use `console.log` in production code — use pino.
107- Do not bypass input validation at API boundaries.
108- Do not leave unhandled promise rejections.
109- Do not hardcode secrets, ports, or environment-specific values.
110- Do not add `disable-model-invocation`; this is a normal domain skill.
111
112## When To Load References
113
114- `references/stack.md`
115 Always.
116
117- `references/bun-runtime.md`
118 When the project uses Bun (detected via `bun.lockb` or `bunfig.toml`).
119
120- then only the task-relevant files under `references/`
121
122## Output Contract
123
124Report:
125
1261. which references were loaded
1272. the architecture pattern chosen
1283. the change made
1294. the verification run