with one click
nodejs-best-practices
// Node.js development principles and decision-making. Framework selection, async patterns, security, and architecture. Teaches thinking, not copying.
// Node.js development principles and decision-making. Framework selection, async patterns, security, and architecture. Teaches thinking, not copying.
Run the correct validation checks for changed files in this repository (Bun frontend checks, uv Python checks, and workflow or guidance verification).
Bootstrap Copilot guidance for any repository by creating or updating `.github/workflows/copilot-setup-steps.yml`, focused lint/check/test workflows, `.github/instructions/*.instructions.md`, and `.github/skills/*/SKILL.md`. Use when asked to initialize Copilot guidance, scaffold repo instructions or skills, create or update `copilot-setup-steps`, or add Copilot-facing validation workflows.
A comprehensive guide for GitHub Copilot to craft immersive, high-performance web experiences with advanced motion, typography, and architectural craftsmanship.
Build Model Context Protocol (MCP) servers with tools, resources, and prompts. Use when creating MCP servers, choosing stdio vs HTTP transport, debugging MCP behavior, or implementing MCP patterns in Python or TypeScript.
| name | nodejs-best-practices |
| description | Node.js development principles and decision-making. Framework selection, async patterns, security, and architecture. Teaches thinking, not copying. |
Principles and decision-making for Node.js development in 2025. Learn to THINK, not memorize code patterns.
This skill teaches decision-making principles, not fixed code to copy.
What are you building?
ā
āāā Edge/Serverless (Cloudflare, Vercel)
ā āāā Hono (zero-dependency, ultra-fast cold starts)
ā
āāā High Performance API
ā āāā Fastify (2-3x faster than Express)
ā
āāā Enterprise/Team familiarity
ā āāā NestJS (structured, DI, decorators)
ā
āāā Legacy/Stable/Maximum ecosystem
ā āāā Express (mature, most middleware)
ā
āāā Full-stack with frontend
āāā Next.js API Routes or tRPC
| Factor | Hono | Fastify | Express |
|---|---|---|---|
| Best for | Edge, serverless | Performance | Legacy, learning |
| Cold start | Fastest | Fast | Moderate |
| Ecosystem | Growing | Good | Largest |
| TypeScript | Native | Excellent | Good |
| Learning curve | Low | Medium | Low |
Node.js 22+: --experimental-strip-types
āāā Run .ts files directly
āāā No build step needed for simple projects
āāā Consider for: scripts, simple APIs
ESM (import/export)
āāā Modern standard
āāā Better tree-shaking
āāā Async module loading
āāā Use for: new projects
CommonJS (require)
āāā Legacy compatibility
āāā More npm packages support
āāā Use for: existing codebases, some edge cases
| Runtime | Best For |
|---|---|
| Node.js | General purpose, largest ecosystem |
| Bun | Performance, built-in bundler |
| Deno | Security-first, built-in TypeScript |
Request Flow:
ā
āāā Controller/Route Layer
ā āāā Handles HTTP specifics
ā āāā Input validation at boundary
ā āāā Calls service layer
ā
āāā Service Layer
ā āāā Business logic
ā āāā Framework-agnostic
ā āāā Calls repository layer
ā
āāā Repository Layer
āāā Data access only
āāā Database queries
āāā ORM interactions
Pattern:
āāā Create custom error classes
āāā Throw from any layer
āāā Catch at top level (middleware)
āāā Format consistent response
Client gets:
āāā Appropriate HTTP status
āāā Error code for programmatic handling
āāā User-friendly message
āāā NO internal details (security!)
Logs get:
āāā Full stack trace
āāā Request context
āāā User ID (if applicable)
āāā Timestamp
| Situation | Status | When |
|---|---|---|
| Bad input | 400 | Client sent invalid data |
| No auth | 401 | Missing or invalid credentials |
| No permission | 403 | Valid auth, but not allowed |
| Not found | 404 | Resource doesn't exist |
| Conflict | 409 | Duplicate or state conflict |
| Validation | 422 | Schema valid but business rules fail |
| Server error | 500 | Our fault, log everything |
| Pattern | Use When |
|---|---|
async/await | Sequential async operations |
Promise.all | Parallel independent operations |
Promise.allSettled | Parallel where some can fail |
Promise.race | Timeout or first response wins |
I/O-bound (async helps):
āāā Database queries
āāā HTTP requests
āāā File system
āāā Network operations
CPU-bound (async doesn't help):
āāā Crypto operations
āāā Image processing
āāā Complex calculations
āāā ā Use worker threads or offload
Where to validate:
āāā API entry point (request body/params)
āāā Before database operations
āāā External data (API responses, file uploads)
āāā Environment variables (startup)
| Library | Best For |
|---|---|
| Zod | TypeScript first, inference |
| Valibot | Smaller bundle (tree-shakeable) |
| ArkType | Performance critical |
| Yup | Existing React Form usage |
Trust nothing:
āāā Query params ā validate
āāā Request body ā validate
āāā Headers ā verify
āāā Cookies ā validate
āāā File uploads ā scan
āāā External APIs ā validate response
| Type | Purpose | Tools |
|---|---|---|
| Unit | Business logic | node:test, Vitest |
| Integration | API endpoints | Supertest |
| E2E | Full flows | Playwright |
node --test src/**/*.test.ts
āāā No external dependency
āāā Good coverage reporting
āāā Watch mode available
Before implementing:
Remember: Node.js best practices are about decision-making, not memorizing patterns. Every project deserves fresh consideration based on its requirements.