Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
xobotyi avatar

Nodejs

  • 3 installs
  • 19 repo stars
  • Updated August 1, 2026
  • xobotyi/cc-foundry

Helps with ai & agent building tasks.

About

nodejs is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.

  • nodejs
  • AI & Agent Building
  • AI-coding skill

Nodejs by the numbers

  • 3 all-time installs (skills.sh)
  • Ranked #13,677 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/xobotyi/cc-foundry --skill nodejs

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs3
repo stars19
Last updatedAugust 1, 2026
Repositoryxobotyi/cc-foundry

What it does

Helps with ai & agent building tasks.

Files

SKILL.mdMarkdownGitHub ↗

Node.js

Respect the event loop. Every blocking operation is a scalability bug.

Node.js rewards async-first, stream-oriented code. If your Node.js code fights the event loop, it's wrong.

References

TopicReferenceContents
Module system[${CLAUDE_SKILL_DIR}/references/modules.md]ESM/CJS comparison tables, file extension rules, conditional exports patterns
Event loop[${CLAUDE_SKILL_DIR}/references/event-loop.md]Phase order, execution priority, blocking operations table, worker pool
Streams[${CLAUDE_SKILL_DIR}/references/streams.md]Stream types table, pipeline patterns, backpressure details
Error handling[${CLAUDE_SKILL_DIR}/references/errors.md]Error categories table, global handlers, centralized error handling
Security[${CLAUDE_SKILL_DIR}/references/security.md]Supply chain threats table, HTTP security headers, process hardening

Module System

  • Use ESM. Set "type": "module" in package.json. Use .mjs/.cjs only when

mixing module systems within one package.

  • Use `node:` prefix for all built-in imports: import fs from 'node:fs'. Prevents

package name collision attacks and is unambiguous.

  • Import `process` explicitly. import process from 'node:process'. Never rely on

the process global — explicit imports make dependencies visible.

  • Define `"exports"` in `package.json` for libraries. Encapsulates internals — only

paths listed in "exports" are importable by consumers.

  • Imports at module top. No dynamic import() for statically-known dependencies.
  • Use `import.meta.dirname`/`import.meta.filename` instead of __dirname/__filename.
  • Use `import.meta.resolve()` instead of require.resolve() in ESM.
  • Always set `"type"` explicitly in package.json, even in CJS packages — future-proofs

the package and helps tooling.

  • Use conditional exports for dual CJS/ESM packages. Order: types > import >

require > default. Always include "default" as fallback.

  • Place `"types"` first in conditional exports when publishing TypeScript declarations.
  • Use `#` imports ("imports" in package.json) for clean internal paths without

../../../. Supports conditional resolution for platform-specific implementations.

  • Keep `"main"` alongside `"exports"` only for backward compatibility with old Node.js

or bundlers. Never use "main" alone for new packages.

  • JSON imports in ESM require with { type: 'json' } attribute.
  • Use `createRequire()` from node:module only when you must require() in ESM

(e.g., native addons).

  • CJS interop: default import from CJS always works. Named imports work if CJS uses

static export patterns; otherwise destructure the default.

  • `require()` can load synchronous ESM (no top-level await). For ESM with

top-level await, use dynamic import().

  • Self-referencing: a package can import its own exports by name when "exports" is

defined.

File extension rules and ESM vs CJS comparison tables: see ${CLAUDE_SKILL_DIR}/references/modules.md.

Event Loop

Node.js uses a single-threaded event loop for JavaScript and a libuv worker pool for expensive I/O and CPU tasks.

Core Rules

  • Never block the event loop. No sync I/O in servers (readFileSync, execSync,

crypto.pbkdf2Sync, zlib.inflateSync). Sync APIs are acceptable only in CLI scripts, startup code, or build tools.

  • Offload CPU-intensive work to worker_threads or child processes. For main-thread

CPU work, partition into chunks with setImmediate() between iterations.

  • Bound input sizes. Unbounded JSON.parse, JSON.stringify, regex, or iteration =

DoS vector. A 50MB JSON string blocks the loop for ~2 seconds.

  • Avoid vulnerable regex. No nested quantifiers (a+)*, no overlapping alternations

(a|a)*, no backreferences with repetition. Use safe-regex2, RE2, or indexOf.

  • Prefer `setImmediate()` over recursive `process.nextTick()`. nextTick starves I/O

if called recursively. Use nextTick only when you must run before any I/O in the current tick (e.g., emitting events after construction before listeners attach).

  • Prefer `queueMicrotask()` over process.nextTick() for new code — it's

cross-platform and web-standard.

  • Inside I/O callbacks, `setImmediate` always fires before `setTimeout(fn, 0)`. Outside

I/O, the order is non-deterministic — do not depend on it.

  • Use `AbortController` for cancellable timers and operations.

Phase order, execution priority, blocking operations table, and worker pool details: see ${CLAUDE_SKILL_DIR}/references/event-loop.md.

Streams

Streams process data incrementally — use them for large files, HTTP bodies, data transformation pipelines, and proxying. Do not use streams when data is already fully in memory.

Core Rules

  • Use `pipeline()` from node:stream/promises for stream composition. Never manual

.pipe() chains — they don't propagate errors or handle cleanup.

  • Respect backpressure. Check .write() return value; wait for 'drain' event before

continuing. pipeline() handles this automatically.

  • Prefer `Readable.from()` for converting iterables/async iterables to streams.
  • Use async iteration (for await (const chunk of stream)) as the simplest way to

consume readable streams. Backpressure is handled automatically.

  • Use `readline` with `createInterface` for line-by-line file processing.
  • `highWaterMark` defaults to 16 KiB for byte streams, 16 objects for object mode.

It's a hint, not a hard limit.

  • Object mode streams count objects (not bytes) against highWaterMark. Enable with

{ objectMode: true }.

  • Destroy streams explicitly when you need to abort: stream.destroy(new Error('msg')).
  • Custom Readable: prefer async generators with Readable.from() over class-based

_read() implementation unless you need fine-grained control.

  • Custom Transform: implement _transform(chunk, encoding, callback) and optionally

_flush(callback) for end-of-stream processing.

  • Custom Writable: implement _write(chunk, encoding, callback) and optionally

_final(callback) for cleanup before 'finish' event.

Stream types table and .pipe() pitfalls: see ${CLAUDE_SKILL_DIR}/references/streams.md.

Error Handling

Core Rules

  • Use `async`/`await` with `try`/`catch`. No callbacks for new code.
  • Always `return await` when returning promises from try blocks — preserves full

stack traces and ensures catch fires for rejections.

  • Extend `Error`. Custom errors must extend Error, set a code property for

programmatic matching (not message strings, which change), and set name.

  • Use `error.cause` for chaining: new Error("context", { cause: originalErr }).

The full chain is visible via util.inspect() and structured loggers.

  • Match errors by `error.code` or `instanceof`, never by message string.
  • Register global handlers. Always handle process.on('unhandledRejection') and

process.on('uncaughtException'). Log, clean up, exit. Since Node.js 15+, unhandled rejections crash the process by default.

  • Never resume after `uncaughtException`. The process state is unknown — log, cleanup,

exit.

  • Subscribe to `'error'` events on all EventEmitters and streams. An unhandled 'error'

event crashes the process. pipeline() handles stream errors automatically.

  • Handle `process.on('warning')` for non-fatal process warnings (deprecations, memory

leaks, experimental features).

  • Use centralized error handlers. Don't scatter error handling across every middleware.

Use a single error handler that maps error types to HTTP responses without leaking internals.

  • Handle once: log OR throw, not both. catch (e) { log(e); throw e } causes

duplicate logging.

  • Never swallow errors in event handlers — always re-emit or log.

Error categories table and operational vs programmer error strategies: see ${CLAUDE_SKILL_DIR}/references/errors.md.

Process Lifecycle

  • Graceful shutdown. Handle SIGTERM/SIGINT: stop accepting connections, wait for

in-flight requests (with timeout), close DB pools, flush logs, then process.exit(0). Force-exit on timeout.

  • Log to stdout/stderr. Let infrastructure (Docker, systemd) handle log routing.

Use structured JSON logging (pino, winston) in production.

  • Set `NODE_ENV=production` in production. It enables framework optimizations and

disables debug output.

  • Use `npm ci` in CI/production. Never npm install — it ignores lockfile mismatches.

Security

Input Validation

  • Validate everything from outside — request bodies, query params, headers, file

uploads, environment variables from untrusted sources. Use schema validation (zod, ajv, typebox).

  • Limit request body size at the HTTP layer before parsing. Set per-content-type limits.

Unbounded payloads exhaust memory.

  • Validate `Content-Length` header before reading the body.
  • Use streaming JSON parsers (stream-json, @streamparser/json) for very large

JSON payloads.

HTTP Security

  • Configure server timeouts. Defaults are too permissive. Set headersTimeout,

requestTimeout, timeout, keepAliveTimeout, maxRequestsPerSocket.

  • Use security headers (via helmet or equivalent): Strict-Transport-Security,

X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy.

  • Delegate TLS/gzip to reverse proxy. Node.js should not terminate TLS or compress

responses in production — let nginx/HAProxy/cloud LB handle TLS termination, compression, rate limiting, and WAF rules.

Secrets & Process Hardening

  • Never hardcode secrets in source code. Use environment variables from secure vaults.
  • Never commit `.env` files — add to .gitignore.
  • Use `crypto.timingSafeEqual()` for secret comparison (prevents timing attacks).
  • Use `crypto.scrypt()` or `crypto.pbkdf2()` (async versions) for password hashing.
  • Avoid shell injection. Never use exec() with user-controlled strings. Use

execFile() or spawn() with argument arrays.

  • Never use `eval()`, `new Function()`, or dynamic `require()` with user input.
  • Run as non-root in Docker — use a dedicated user.
  • Limit V8 heap with --max-old-space-size to prevent memory exhaustion.

Supply chain threats table, dependency auditing, and security checklist: see ${CLAUDE_SKILL_DIR}/references/security.md.

Application

When writing Node.js code:

  • Apply all conventions silently — don't narrate each rule being followed.
  • If an existing codebase contradicts a convention, follow the codebase and flag the

divergence once.

  • Prefer node:fs/promises over callback-based node:fs.
  • Prefer node:stream/promises for pipeline operations.

When reviewing Node.js code:

  • Cite the specific violation and show the fix inline.
  • Don't lecture or quote the rule — state what's wrong and how to fix it.

Integration

The javascript skill governs language choices; this skill governs Node.js runtime decisions. Activate typescript alongside both when working with TypeScript.

Respect the event loop. When in doubt, make it async.

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.