pattern-engineer-node
Skill0 starsChanged 5 months agoMITView on GitHub
Node.js runtime for server-side JS/TS (Express/Fastify/Hono/Nest): Node LTS via `engines`+`.nvmrc`; ESM; `npm ci`; never block the event loop — no `*Sync`/heavy `JSON.parse` in request paths, CPU to `worker_threads`; `unhandledRejection`/`uncaughtException` exit non-zero; SIGTERM `server.close`+drain; one zod `process.env` config; pino not `console.log`; await/`.catch` promises; `AbortSignal.timeout` on `fetch`; `createApp()` split from listen. Activate on Node server code + `package.json`.
- Reads credentials
In this repository74 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- create-bug-issueSkill
- create-enhancement-issueSkill
- create-feature-issuesSkill
- dream-summary-memorySkill
- memory-conventionSkill
- operation-gitSkill
- pattern-architect-api-endpointSkill
- pattern-architect-data-modelSkill
- pattern-architect-deep-moduleSkill
- pattern-e2e-coding-standardSkill
- pattern-engineer-apiSkill
- pattern-engineer-backend-standardSkill
- pattern-engineer-coding-standardSkill
- pattern-engineer-containerSkill
- pattern-engineer-databaseSkill
- pattern-engineer-fastapiSkill
- pattern-engineer-frontend-standardSkill
- pattern-engineer-goSkill
- pattern-engineer-javaSkill
- pattern-engineer-kotlinSkill
- pattern-engineer-non-functionalSkill
- pattern-engineer-observabilitySkill
- pattern-engineer-pythonSkill
- pattern-engineer-rustSkill
- pattern-engineer-securitySkill
- pattern-engineer-ssrSkill
- pattern-engineer-swiftSkill
- pattern-engineer-typescriptSkill
- pattern-engineer-viteSkill
- pattern-exploratory-testingSkill
- pattern-reviewer-apiSkill
- pattern-reviewer-backend-standardSkill
- pattern-reviewer-coding-standardSkill
- pattern-reviewer-containerSkill
- pattern-reviewer-contractSkill
- pattern-reviewer-databaseSkill
- pattern-reviewer-fastapiSkill
- pattern-reviewer-frontend-standardSkill
- pattern-reviewer-goSkill
- pattern-reviewer-javaSkill
- pattern-reviewer-kotlinSkill
- pattern-reviewer-nodeSkill
- pattern-reviewer-non-functionalSkill
- pattern-reviewer-observabilitySkill
- pattern-reviewer-pythonSkill
- pattern-reviewer-rustSkill
- pattern-reviewer-securitySkill
- pattern-reviewer-ssrSkill
- pattern-reviewer-swiftSkill
- pattern-reviewer-test-coverageSkill
- pattern-reviewer-typescriptSkill
- pattern-reviewer-viteSkill
- pattern-test-coverageSkill
- principle-engineer-tddSkill
- scaffold-projectSkill
- workflow-architect-interviewSkill
- workflow-designer-sample-pagesSkill
- workflow-design-interviewSkill
- workflow-e2e-authorSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 1 is distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 22
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-node.md in the consuming project (resolve …
- Very specific: line 31
No on-the-fly dependency fetching in production code (npm install, dynamic remote import() of untrusted URLs).
- Very specific: line 50
No scattered process.env.X reads through the codebase — modules import the validated config object.
- Very specific: line 62
Every promise is awaited or explicitly fire-and-forget with a .catch(...) — no floating promises.
- Very specific: line 64
Every outbound fetch carries a timeout: fetch(url, { signal: AbortSignal.timeout(ms) }).
- Distinctive: line 71
No side effects at module top level — don't open a DB connection, bind a port, or kick off work at import time.
- Very specific: line 73
No circular imports — they yield undefined exports at load time depending on resolution order.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
pattern-engineer-node
Node-specific runtime discipline for server-side JavaScript/TypeScript: the event loop, process lifecycle, configuration, module hygiene, and the Node toolchain. This is the runtime sibling to pattern-engineer-typescript (which owns the TS language) — the relationship mirrors pattern-engineer-python for the Python backend.
When to activate
Activate when writing or editing server-side JS/TS that runs under Node: Express / Fastify / Hono / Nest handlers and middleware, process-level lifecycle code, process.env config loading, a Node entrypoint or package.json scripts/engines, worker_threads, streams, outbound fetch, or Node test files (vitest / node:test / supertest).
Skip when:
- The code is browser/Vite frontend JS/TS —
pattern-engineer-typescriptandpattern-engineer-viteown that. - The concern is a pure TypeScript language rule (types,
any, discriminated unions,tsconfigstrictness) — that stays inpattern-engineer-typescript. - The concern is language-agnostic backend wiring (
.env.examplelockstep, the SIGTERM concept, retries/backoff,/healthzshape) —pattern-engineer-backend-standardowns it; this skill owns only the Node mechanics of those concepts. Auth/SSRF/secret handling belong topattern-engineer-security.
Project memory overlay
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-node.md in the consuming project (resolve MAIN_ROOT="$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")"). If present, load it as an additive overlay to the rules below; if absent, skip silently. See memory-convention for the full contract (additivity, severity floor, conflict surfacing).
Patterns
Runtime + packaging
- Pin a Node LTS line:
"engines": { "node": ">=20" }inpackage.jsonAND a matching.nvmrc— keep the two in lockstep. - New services are ESM:
"type": "module"inpackage.json; useimport/export, notrequire/module.exports. - Install with
npm ciagainst the committed lockfile (package-lock.json/pnpm-lock.yaml); nevernpm installat runtime or in a container entrypoint. - No on-the-fly dependency fetching in production code (
npm install, dynamic remoteimport()of untrusted URLs).
Don't block the event loop
- No
fs.*Sync,crypto.*Sync(randomBytes/scryptSync/pbkdf2Sync),zlib.*Sync, orchild_process.execSyncin a request path — use the async/promisesform. - CPU-heavy work (hashing big buffers, image/crypto, large parse/transform) goes to
worker_threads(or a queue), not the main thread. - Beware multi-MB
JSON.parse/JSON.stringifyon hot paths — they block synchronously; stream or bound the size. - Tight synchronous loops over large arrays block too; chunk or offload.
Process lifecycle (Node mechanics of the backend-standard SIGTERM rule)
- Register
process.on('unhandledRejection', …)andprocess.on('uncaughtException', …): log structurally, then exit non-zero — never keep serving in an unknown state. - On
SIGTERM(andSIGINT): stop accepting new work (server.close(...)), let in-flight requests drain, close DB pools / queue connections, flush logs, thenprocess.exit(0). - Arm a hard-exit timeout fallback (
setTimeout(() => process.exit(1), N).unref()) so a stuck drain can't hang shutdown forever. .unref()background timers/intervals so they don't pin the process open during shutdown.
Config — one typed module
- One config module validates
process.envat boot with a zod schema and fails fast, reporting the full list of missing/invalid keys at once. - No scattered
process.env.Xreads through the codebase — modules import the validated config object. dotenvis loaded only in the dev entrypoint (or vianode --env-file), neverimported at production module scope.- (
.env.examplelockstep is owned bypattern-engineer-backend-standard.)
Logging
pino(or equivalent structured JSON logger), one instance per service.- No
console.log/console.errorin production request paths. - Child loggers carry correlation context:
logger.child({ request_id })per request.
Async correctness
- Every promise is
awaited or explicitly fire-and-forget with a.catch(...)— no floating promises. - Express (≤4) async route handlers are wrapped (
express-async-handleror awrap(fn)) so rejections reach the error middleware; Express 5 / Fastify handle async rejection natively. - Every outbound
fetchcarries a timeout:fetch(url, { signal: AbortSignal.timeout(ms) }). - Choose
Promise.all(fail-fast) vsPromise.allSettled(collect all) deliberately, per call site. - Compose streams with
stream.pipeline()(orpipelinefromnode:stream/promises) — never barea.pipe(b).pipe(c)chains that drop errors and leak handles. - No
array.forEach(async …)— it ignores the returned promise (also flagged bypattern-engineer-typescript).
Module hygiene
- No side effects at module top level — don't open a DB connection, bind a port, or kick off work at import time.
- Export a
createApp()factory that builds and returns the app/server; a separate entrypoint (server.ts/index.ts) callscreateApp()then.listen(...), so tests inject the app without binding a port. - No circular imports — they yield
undefinedexports at load time depending on resolution order; break the cycle with a shared module or dependency injection.
Tests
vitest(ornode:test) as the runner.- HTTP tests run against the app factory:
supertest(createApp())for Express, Fastify'sapp.inject(...)— never spin up a real listening port. - Fake timers (
vi.useFakeTimers()) for time-dependent logic (timeouts, retries, intervals) instead of realsetTimeoutwaits. - (Coverage substance — what to test — lives in the shared
pattern-test-coverage.)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

