Production-ready Node.js API skeleton built with Hexagonal Architecture, Fastify, TypeScript, DDD, and modern best practices. Perfect starting point for scalable, maintainable API projects.
Version 2.0 - Migration to Hexagonal Architecture + Fastify COMPLETED!
All 8 migration stages completed β
- β Stage 0: SWC compiler, Fastify dependencies, path aliases
- β Stage 1: Hexagonal folder structure, Zod validation, Fastify server
- β Stage 2: Domain layer (entities, value objects, ports)
- β Stage 3: Application layer (use cases, DTOs, mappers)
- β Stage 4: Infrastructure layer (controllers, routes, repositories)
- β Stage 5: Dependency Injection with Awilix
- β Stage 6: Observability (Winston logging + Prometheus metrics)
- β Stage 7: Testing (Vitest + k6 performance tests)
- β Stage 8: Cleanup, documentation, Docker production setup
π Table of Contents
- Hexagonal Architecture (Ports & Adapters) for clean separation of concerns
- Onion Architecture with dependency inversion
- Screaming Architecture - folder structure reflects business capabilities
- DDD (Domain-Driven Design) with entities, value objects, and aggregates
- Vertical Slice organization by bounded contexts
- Fastify - 2x faster than Express
- SWC - Ultra-fast TypeScript compiler (20x faster than tsc)
- Build time: ~56ms (was ~2-3s with tsc)
- Production-ready with Docker multi-stage builds
- Vitest - Lightning-fast unit & integration tests
- k6 - Performance/load testing with thresholds
- 98%+ coverage - 244 comprehensive tests across all layers
- Type-safe validation with Zod
- ESLint + Prettier - Code quality enforcement
- Winston - Structured JSON logging
- Prometheus - Metrics collection (requests, latency, errors)
- Grafana - Metrics visualization
- Health checks - Liveness & readiness probes
- OpenAPI - Interactive API documentation
- Docker multi-stage builds (minimal Alpine images)
- Docker Compose stacks for dev & production
- Non-root user for security
- Health checks integrated
- Prometheus + Grafana stack included
- β Fastify - High-performance web framework
- β TypeScript - Type-safe JavaScript
- β SWC - Ultra-fast TypeScript compiler
- β Zod - Runtime schema validation
- β Awilix - Dependency injection
- β Vitest - Fast unit & integration tests
- β Supertest - HTTP endpoint testing
- β k6 - Load & performance testing
- β Pact - Contract testing framework
- β Coverage reports with v8
- β Winston - Structured logging
- β Prometheus - Metrics collection
- β prom-client - Prometheus client
- β Health checks (liveness/readiness)
- β Swagger/OpenAPI - API documentation
- β @fastify/helmet - Security headers
- β @fastify/cors - CORS support
- β @fastify/rate-limit - Rate limiting
- β Environment validation with Zod
- β Docker non-root user
- β Immutable domain entities
- β ADRs (Architecture Decision Records)
- β ESLint - Code linting
- β Prettier - Code formatting
- β Husky - Git hooks
- β lint-staged - Pre-commit checks
- β Nodemon - Dev server auto-reload
The application follows Hexagonal Architecture (Ports & Adapters):
βββββββββββββββββββββββββββββββββββββββββββ
β Infrastructure (Adapters) β β Fastify, DB, External APIs
βββββββββββββββββββββββββββββββββββββββββββ€
β Application (Use Cases) β β Business orchestration
βββββββββββββββββββββββββββββββββββββββββββ€
β Domain (Business Logic) β β Pure business rules
βββββββββββββββββββββββββββββββββββββββββββ
Dependency Rule: Dependencies point inward only
- Infrastructure β Application β Domain
- Domain has zero framework dependencies
Each bounded context is a complete vertical slice:
@contexts/greetings/
βββ domain/ # Entities, Value Objects, Business Rules
βββ application/ # Use Cases, DTOs, Mappers, Ports
βββ infrastructure/ # Controllers, Routes, Repositories
Benefits:
- High cohesion - related code lives together
- Easy to navigate - no jumping between layers
- Scalable - add new contexts without touching existing ones
- Microservices-ready - easy to extract contexts
See ARCHITECTURE.md for complete documentation.
src/
βββ @contexts/ # Business Features (Bounded Contexts)
β βββ greetings/
β βββ domain/ # Business Logic (framework-independent)
β β βββ entities/ # Greeting entity
β β βββ value-objects/ # Message value object
β β βββ exceptions/ # Domain exceptions
β βββ application/ # Use Cases & Orchestration
β β βββ v1/ # API version 1
β β β βββ use-cases/ # GetGreetingUseCase
β β β βββ dtos/ # Request/Response DTOs
β β β βββ mappers/ # Domain β DTO transformation
β β β βββ ports/ # Interfaces (inbound/outbound)
β β βββ v2/ # API version 2 (enhanced)
β βββ infrastructure/ # Adapters (HTTP, DB, External)
β βββ http/ # Controllers & Routes (v1, v2)
β βββ persistence/ # Repository implementations
β
βββ @shared/ # Cross-Cutting Concerns
β βββ domain/ # Shared domain concepts
β βββ infrastructure/
β β βββ config/ # Environment, DI container
β β βββ http/ # Fastify app, plugins
β β βββ observability/ # Winston, Prometheus
β βββ types/ # Common types
β βββ utils/ # Pure utility functions
β βββ constants/ # HTTP status codes, etc.
β
βββ @app/ # Application Bootstrap
β βββ server/ # Fastify configuration
β
βββ main.ts # Entry point
- Node.js >= 20
- npm >= 10
- Docker (optional, for containerized setup)
- k6 (optional, for performance tests)
# Clone repository
git clone https://github.com/Proskynete/node-api-skeleton.git
cd node-api-skeleton
# Install dependencies
npm install
# Copy environment file
cp .env.example .env
# Start development server
npm run devThe API will be running at http://localhost:3000
# Development
npm run dev # Start dev server with hot reload (SWC)
npm run build # Build production bundle (SWC)
npm start # Run production server
# Testing
npm run test # Run all tests (Vitest)
npm run test:watch # Run tests in watch mode
npm run test:ui # Run tests with UI dashboard
npm run test:coverage # Generate coverage report
# Performance Testing (k6)
npm run test:performance:v1 # Test v1 endpoint
npm run test:performance:v2 # Test v2 endpoint
npm run test:performance:load # Full load test
# Code Quality
npm run lint # Check linting
npm run lint:fix # Fix linting issues
npm run format # Format code with Prettier
npm run format:check # Check formattingThe project uses Docker Compose profiles for managing development and production environments in a single configuration file.
# Start production stack (API + Prometheus + Grafana)
docker-compose --profile production up -d
# View logs
docker-compose logs -f api-prod
# Stop services
docker-compose --profile production down# Start dev environment with hot reload
docker-compose --profile dev up -d
# View logs
docker-compose logs -f api-dev
# Stop services
docker-compose --profile dev down- API: http://localhost:3000
- Prometheus: http://localhost:9090
- Grafana: http://localhost:3001 (admin/admin)
See DOCKER.md for complete documentation.
- Liveness:
GET /health/live- Is the app running? - Readiness:
GET /health/ready- Can it serve traffic? - Metrics:
GET /metrics- Prometheus metrics - Docs:
GET /docs- Swagger UI
- Get Greeting:
GET /api/v1/greetings
- Get Greeting (enhanced):
GET /api/v2/greetings
API Versioning: Multiple versions coexist, sharing the same domain layer but with different use cases.
The project includes 244 tests across all layers with excellent coverage:
Coverage Stats (as of v2.1.0):
- β Statements: 98.42%
- β Branches: 84.00%
- β Functions: 96.87%
- β Lines: 98.38%
Coverage Thresholds: 80% minimum for all metrics
Test business logic in isolation:
npm run test # Run all tests
npm run test:watch # Watch mode
npm run test:ui # Interactive UI dashboard
npm run test:coverage # Generate coverage reportTest Coverage by Layer:
Domain Layer (Pure business logic):
DomainEvent.spec.ts- Base domain event class (12 tests)GreetingCreatedEvent.spec.ts- Greeting domain event (21 tests)Greeting.spec.ts- Greeting entityMessage.spec.ts- Message value object
Application Layer (Use cases & orchestration):
GetGreetingUseCase.spec.ts(v1 and v2) - Business workflows (19 tests each)GreetingMapper.spec.ts(v1 and v2) - Data transformations (29 tests v2)GreetingCreatedEventHandler.spec.ts- Event handling (13 tests)InMemoryDomainEventPublisher.spec.ts- Event publishing (29 tests)
Infrastructure Layer (Repositories):
InMemoryGreetingRepository.spec.ts- Data persistence (19 tests)
Architecture Principle: Infrastructure adapters (controllers, middlewares, plugins, route loaders) are excluded from unit test coverage as they're validated through integration/E2E tests. This aligns with Hexagonal Architecture best practices.
Test HTTP endpoints and infrastructure:
describe("GET /api/v1/greetings", () => {
it("should return greeting", async () => {
const response = await request(app.server)
.get("/api/v1/greetings")
.expect(200);
expect(response.body.message).toBe("Hello World!");
});
});Integration Test Coverage:
- HTTP endpoints (v1 and v2)
- Rate limiting
- Health checks
- Metrics collection
- Error handling
Load testing with strict performance thresholds:
npm run test:performance:v1 # Test v1 endpoint
npm run test:performance:v2 # Test v2 endpoint
npm run test:performance:load # Full load testPerformance Thresholds:
- p95 latency < 500ms
- p99 latency < 1000ms
- Error rate < 1%
- Request rate > 50 req/s
See test/performance/README.md
Consumer-driven contract testing ensures API compatibility:
npm run test:contract:providerStructured JSON logging in production, pretty logs in development:
logger.info("Processing request", {
requestId: request.id,
version: "v1",
});Available at /metrics:
http_request_duration_seconds- Request latencyhttp_requests_total- Total requestshttp_requests_in_progress- Active requests
- Liveness:
/health/live- Basic health check - Readiness:
/health/ready- Dependency health (memory, DB, etc.)
Interactive API docs at:
- Swagger UI: http://localhost:3000/docs
- ARCHITECTURE.md - Complete architecture guide (Hexagonal + DDD + Vertical Slices)
- DOCKER.md - Docker setup, multi-stage builds, and Docker Compose
- GITHUB_ACTIONS.md - CI/CD pipeline, workflows, and automation
- CLAUDE.md - Development guide for Claude Code AI assistant
Document key architectural decisions with context and consequences:
- ADR Index - Complete list of architectural decisions
- ADR-0001 - Hexagonal Architecture adoption
- ADR-0007 - Bounded Contexts organization
- ADR-0009 - OOP + FP hybrid approach
- Performance Testing - k6 load testing, thresholds, and automated test runner
- Contract Testing - Provider - Pact provider tests for HTTP inbound adapters
- Contract Testing - Consumer - Pact consumer tests reference (HTTP outbound adapters)
- Contract Tests README - Contract testing overview and execution
- Database Integration - Prisma setup and repository implementation guide
- Scripts README - Automated performance test runner documentation
- Dependency Injection (Awilix)
- Factory Pattern (Entity creation)
- Mapper Pattern (Domain β DTO)
- Repository Pattern (Data access)
- Strategy Pattern (API versioning)
- Helmet security headers
- CORS configuration
- Input validation with Zod
- Non-root Docker user
- Environment variable validation
Contributions are welcome! Please read CONTRIBUTING.md for guidelines.
This project is licensed under the MIT License.
- Built with β€οΈ using modern Node.js best practices
- Inspired by Clean Architecture, DDD, and Hexagonal Architecture principles
Version: 2.1.0 Status: Production Ready Architecture: Hexagonal + Onion + Screaming Last Updated: December 2024