Refactor high-complexity React components in Dify frontend. Use when `pnpm analyze-component...
npx skills add sickn33/antigravity-awesome-skills --skill "nodejs-best-practices"
Install specific skill from multi-skill repository
# Description
Node.js development principles and decision-making. Framework selection, async patterns, security, and architecture. Teaches thinking, not copying.
# SKILL.md
name: nodejs-best-practices
description: Node.js development principles and decision-making. Framework selection, async patterns, security, and architecture. Teaches thinking, not copying.
allowed-tools: Read, Write, Edit, Glob, Grep
Node.js Best Practices
Principles and decision-making for Node.js development in 2025.
Learn to THINK, not memorize code patterns.
β οΈ How to Use This Skill
This skill teaches decision-making principles, not fixed code to copy.
- ASK user for preferences when unclear
- Choose framework/pattern based on CONTEXT
- Don't default to same solution every time
1. Framework Selection (2025)
Decision Tree
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
Comparison Principles
| 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 |
Selection Questions to Ask:
- What's the deployment target?
- Is cold start time critical?
- Does team have existing experience?
- Is there legacy code to maintain?
2. Runtime Considerations (2025)
Native TypeScript
Node.js 22+: --experimental-strip-types
βββ Run .ts files directly
βββ No build step needed for simple projects
βββ Consider for: scripts, simple APIs
Module System Decision
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 Selection
| Runtime | Best For |
|---|---|
| Node.js | General purpose, largest ecosystem |
| Bun | Performance, built-in bundler |
| Deno | Security-first, built-in TypeScript |
3. Architecture Principles
Layered Structure Concept
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
Why This Matters:
- Testability: Mock layers independently
- Flexibility: Swap database without touching business logic
- Clarity: Each layer has single responsibility
When to Simplify:
- Small scripts β Single file OK
- Prototypes β Less structure acceptable
- Always ask: "Will this grow?"
4. Error Handling Principles
Centralized Error Handling
Pattern:
βββ Create custom error classes
βββ Throw from any layer
βββ Catch at top level (middleware)
βββ Format consistent response
Error Response Philosophy
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
Status Code Selection
| 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 |
5. Async Patterns Principles
When to Use Each
| 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 |
Event Loop Awareness
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
Avoiding Event Loop Blocking
- Never use sync methods in production (fs.readFileSync, etc.)
- Offload CPU-intensive work
- Use streaming for large data
6. Validation Principles
Validate at Boundaries
Where to validate:
βββ API entry point (request body/params)
βββ Before database operations
βββ External data (API responses, file uploads)
βββ Environment variables (startup)
Validation Library Selection
| Library | Best For |
|---|---|
| Zod | TypeScript first, inference |
| Valibot | Smaller bundle (tree-shakeable) |
| ArkType | Performance critical |
| Yup | Existing React Form usage |
Validation Philosophy
- Fail fast: Validate early
- Be specific: Clear error messages
- Don't trust: Even "internal" data
7. Security Principles
Security Checklist (Not Code)
- [ ] Input validation: All inputs validated
- [ ] Parameterized queries: No string concatenation for SQL
- [ ] Password hashing: bcrypt or argon2
- [ ] JWT verification: Always verify signature and expiry
- [ ] Rate limiting: Protect from abuse
- [ ] Security headers: Helmet.js or equivalent
- [ ] HTTPS: Everywhere in production
- [ ] CORS: Properly configured
- [ ] Secrets: Environment variables only
- [ ] Dependencies: Regularly audited
Security Mindset
Trust nothing:
βββ Query params β validate
βββ Request body β validate
βββ Headers β verify
βββ Cookies β validate
βββ File uploads β scan
βββ External APIs β validate response
8. Testing Principles
Test Strategy Selection
| Type | Purpose | Tools |
|---|---|---|
| Unit | Business logic | node:test, Vitest |
| Integration | API endpoints | Supertest |
| E2E | Full flows | Playwright |
What to Test (Priorities)
- Critical paths: Auth, payments, core business
- Edge cases: Empty inputs, boundaries
- Error handling: What happens when things fail?
- Not worth testing: Framework code, trivial getters
Built-in Test Runner (Node.js 22+)
node --test src/**/*.test.ts
βββ No external dependency
βββ Good coverage reporting
βββ Watch mode available
10. Anti-Patterns to Avoid
β DON'T:
- Use Express for new edge projects (use Hono)
- Use sync methods in production code
- Put business logic in controllers
- Skip input validation
- Hardcode secrets
- Trust external data without validation
- Block event loop with CPU work
β DO:
- Choose framework based on context
- Ask user for preferences when unclear
- Use layered architecture for growing projects
- Validate all inputs
- Use environment variables for secrets
- Profile before optimizing
11. Decision Checklist
Before implementing:
- [ ] Asked user about stack preference?
- [ ] Chosen framework for THIS context? (not just default)
- [ ] Considered deployment target?
- [ ] Planned error handling strategy?
- [ ] Identified validation points?
- [ ] Considered security requirements?
Remember: Node.js best practices are about decision-making, not memorizing patterns. Every project deserves fresh consideration based on its requirements.
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.