- TypeScript 84.6%
- JavaScript 11.9%
- Shell 3.2%
- Makefile 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
Some checks failed
CI / Core Gates (build · typecheck · test · lint · tasks) (push) Has been cancelled
CI / Scaffold Smoke (template · scaffold · install · build · test) (push) Has been cancelled
Scaffold Integration Matrix / Scaffold Leg a (template · scaffold · install · build) (push) Has been cancelled
Scaffold Integration Matrix / Scaffold Leg b (template · scaffold · install · build) (push) Has been cancelled
Scaffold Integration Matrix / Scaffold Leg c (template · scaffold · install · build) (push) Has been cancelled
Scaffold Integration Matrix / Scaffold Leg d (template · scaffold · install · build) (push) Has been cancelled
create-node-ddd-app@0.1.0 is live on npm (manual publish, 2FA). Mark scaffolding-publish-config done, add the scaffolding-ci-publish follow-up (tag-triggered publish once Forgejo Actions is confirmed), re-rank the roadmap "Now" to station 0.2.0, tick the 0.1.0 release checkbox, and record the checkpoint in the Decisions Log with the review verdict. Retire .build.yml: the repo moved from sourcehut to git.marric.quest/riccardo/create-node-ddd-app. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CEfCdS1MkqWTG8ANAs8UMg |
||
| .claude | ||
| .github/workflows | ||
| .husky | ||
| .omp | ||
| .playwright-mcp | ||
| .serena | ||
| .tasks | ||
| .vscode | ||
| apps | ||
| docker | ||
| docs | ||
| packages | ||
| scripts | ||
| todo | ||
| tools | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .mcp.json | ||
| .prettierignore | ||
| .prettierrc | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| commitlint.config.js | ||
| CONTRIBUTING.md | ||
| docker-compose.override.yml.dist | ||
| docker-compose.yml | ||
| docker.sh | ||
| Dockerfile | ||
| eslint.config.mjs | ||
| LICENSE | ||
| Makefile | ||
| nx.json | ||
| opencode.json | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| sgconfig.yml | ||
| test-authorization.mjs | ||
| test-debug.mjs | ||
| test-endpoints.mjs | ||
| test-health.sh | ||
| test-update-only.mjs | ||
| tsconfig.base.json | ||
| tsconfig.json | ||
| tsconfig.tsmorph.json | ||
| tsconfig.tsmorph.with-tests.json | ||
Effect CQRS + Event Sourcing Template
A production-ready TypeScript template implementing CQRS (Command Query Responsibility Segregation) and Event Sourcing patterns using Domain-Driven Design (DDD) and Hexagonal Architecture. Built with Effect and Nx.
🎯 What is This?
This is a template project demonstrating:
- ✅ DDD - Domain-Driven Design with bounded contexts
- ✅ CQRS - Separate write (commands) and read (queries) models
- ✅ Event Sourcing - Complete audit trail of state changes
- ✅ Hexagonal Architecture - Pluggable adapters for infrastructure
- ✅ Clean Architecture - Testable, maintainable, technology-agnostic
- ✅ Type Safety - Full TypeScript with Effect for typed error handling
Perfect for building scalable, maintainable event-driven applications.
🚀 Quick Start
Fastest Option: Docker (Recommended)
# Clone the repository
git clone <repo-url>
cd create-node-ddd-app
# Start with in-memory adapters (fastest)
./docker.sh dev
# Or start with PostgreSQL (event store + projections)
./docker.sh postgres
# View all available commands
./docker.sh
The API will be available at:
- Dev mode: http://localhost:3000
- PostgreSQL: http://localhost:3002
Visit /docs for interactive Swagger API documentation.
Local Development
# Install dependencies
pnpm install
# Build the application
pnpm nx run runner:build
# Run the application
node apps/runner/dist/index.js
Expected output (abridged):
🔧 Application Configuration:
├─ Environment: development
├─ Event Store: memory
├─ Event Bus: memory
├─ Auth Provider: memory
├─ Telemetry: noop
├─ Projections:
│ └─ PostListView: memory
└─ Servers:
├─ HTTP REST: enabled (port 3000)
├─ Web SSR: enabled (port 3001)
├─ gRPC: disabled
└─ WebSocket: disabled
✅ Runner: Application started successfully
🚀 CQRS + Event Sourcing architecture active
🌐 REST API: http://localhost:3000
📚 Swagger Docs: http://localhost:3000/docs
With zero configuration, the runner seeds a canonical in-memory PostListView projection (set PROJECTION_DEFAULT=none to opt out).
📋 Table of Contents
Core Documentation
- docs/SETUP.md - Complete setup and development guide
- docs/ARCHITECTURE.md - System design and patterns
- docs/TESTING.md - Testing strategy and execution
- docs/SECURITY.md - Security guidelines
- docs/TELEMETRY.md - Observability with SigNoz
Product & Planning
- docs/product/VISION.md - Product vision and goals
- docs/product/ROADMAP.md - Development roadmap
- docs/product/user-stories/ - Feature requirements
Architecture Decisions
- docs/decisions/ - Architecture Decision Records (ADRs)
- docs/rfcs/ - Request for Comments
For LLM Agents
- CLAUDE.md - LLM-specific navigation and rules
🔄 CQRS + Event Sourcing Flow
┌─────────────┐
│ Client │
└──────┬──────┘
│
▼
┌─────────────────────────────────────┐
│ REST API (port 3000) │
│ Commands │ Queries │
└────────┬────────┴────────┬───────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────┐
│ Write Model │ │ Read Model │
│ (PostService) │ │(QueryDB) │
│ ↓ │ │ ↑ │
│ EventStore ─────┼──┼─→ Projector │
└──────────────────┘ └──────────────┘
│ ▲
└───────────────┬─┘
EventBus
(Effect Queue)
💾 API Examples
Create a Post (Command)
curl -X POST http://localhost:3000/posts \
-H "Content-Type: application/json" \
-d '{
"aggregateId": "post-001",
"userId": "user-123",
"title": "My First Post",
"content": "Testing CQRS and Event Sourcing!"
}'
Get a Post (Query)
curl http://localhost:3000/posts/post-001
List All Posts (Query)
curl http://localhost:3000/posts
Publish a Post (Command)
curl -X POST http://localhost:3000/posts/post-001/publish
🏗️ Architecture at a Glance
packages/
├── domain/
│ ├── shared-kernel/ # Core domain primitives (zero dependencies)
│ ├── debate-domain/ # Post aggregate, events, commands, queries
│ └── auth-domain/ # Authentication models
├── application/
│ ├── app/ # Cross-cutting ports, API definitions, error mapping
│ ├── debate-application/ # PostService, PostProjector, contract tests
│ └── auth-application/ # AuthService, AuthorizationService
└── infrastructure/
├── eventstore-inmemory-adapter/ # Event persistence (dev/test)
├── eventstore-postgres-adapter/ # Event persistence (production)
├── database-inmemory-adapter/ # CQRS read model (dev/test)
├── database-postgres-adapter/ # CQRS read model (production)
├── event-queue-adapter/ # Event bus (Effect Queue)
├── http-rest-adapter/ # REST API + Swagger
└── ... # auth, telemetry, grpc, websocket, web-ssr
apps/
└── runner/ # Composition root (wires everything)
Key Principle: Domain is stable. Infrastructure is replaceable. Runner is sacrificial.
🔧 Configuration
The application is configured via environment variables:
# Event persistence (write model)
EVENT_STORE=memory # memory, postgres (eventstoredb: planned)
# Async event distribution
EVENT_BUS=memory # memory (rabbitmq, kafka: planned)
# Read model projections (one block per projection)
# Zero-config boots a canonical in-memory PostListView projection.
PROJECTION_DEFAULT=memory # memory, postgres, none (opt out of seeding)
PROJECTION_POST_LIST_VIEW_TYPE=memory # memory, postgres (mongodb: planned)
# For postgres: PROJECTION_POST_LIST_VIEW_HOST / _PORT / _DATABASE / _USER / _PASSWORD
# Server configuration
HTTP_ENABLED=true
HTTP_PORT=3000
GRPC_ENABLED=false
GRPC_PORT=50051
WEBSOCKET_ENABLED=false
WEBSOCKET_PORT=8080
# Telemetry
TELEMETRY_PROVIDER=noop # noop, signoz
See SETUP.md for detailed configuration guide.
🧪 Testing
# Run all tests
pnpm nx run-many -t test
# Run tests for a specific package
pnpm nx run debate-domain:test
# Run tests with coverage
pnpm nx run shared-kernel:test:coverage
# End-to-end tests
pnpm test:e2e
See TESTING.md for the testing strategy (contract tests, integration tests, coverage expectations per package).
📦 Build and Deploy
Build
pnpm nx run-many -t build
Docker
# Development
./docker.sh dev
# Production setup with PostgreSQL
./docker.sh postgres
# Infrastructure only (for local Node.js debugging)
./docker.sh infra postgres mongodb
See SETUP.md for complete Docker documentation.
🎓 Learning Resources
For Architects
Start with ARCHITECTURE.md to understand:
- System design philosophy
- Design patterns used
- Dependency management
- Why each architectural decision was made
For Developers
Start with SETUP.md to:
- Get your environment running
- Understand the development workflow
- Learn Docker setup and commands
- Configure environment variables
For QA Engineers
See TESTING.md for:
- How to run tests
- Testing strategies
- API endpoint testing examples
- CQRS flow verification
🛠️ Common Tasks
Run the app locally with debugger
# Terminal 1: Start infrastructure
./docker.sh infra postgres
# Terminal 2: Generate environment config
./docker.sh env:local
# Terminal 3: Build and run with inspector
pnpm nx run runner:build
node --inspect apps/runner/dist/index.js
# Connect debugger in Chrome: chrome://inspect
Test multiple adapters
# In-memory (no infrastructure needed)
pnpm nx run-many -t test
# PostgreSQL setup (integration tests)
./docker.sh infra postgres
pnpm nx run-many -t test
# SigNoz observability
./docker.sh infra postgres signoz
# View traces at http://localhost:3301
Add a new feature
- Define domain logic in
packages/domain/ - Define application services and ports in
packages/application/ - Implement adapter in
packages/infrastructure/if needed - Wire in
apps/runner/src/lib/factories.ts
🐛 Troubleshooting
Port Already in Use
HTTP_PORT=4000 node apps/runner/dist/index.js
"Adapter Not Implemented" Error
Use in-memory adapters:
EVENT_STORE=memory EVENT_BUS=memory PROJECTION_DEFAULT=memory node apps/runner/dist/index.js
Docker Issues
# Clean up everything
./docker.sh clean
# Check service health
./docker.sh health
# View logs
./docker.sh logs
📚 Additional Documentation
All documentation is organized under the docs/ folder:
| Category | Description |
|---|---|
| docs/ARCHITECTURE.md | System design, patterns, principles |
| docs/TESTING.md | Testing strategy and execution |
| docs/SETUP.md | Development setup and environment |
| docs/SECURITY.md | Security guidelines |
| docs/TELEMETRY.md | Observability with SigNoz |
| docs/decisions/ | Architecture Decision Records |
| docs/rfcs/ | Request for Comments |
| docs/product/ | Vision, roadmap, user stories |
| docs/templates/ | Document templates (RFC, ADR, LOG) |
| docs/logs/ | Operational logs |
| docs/archive/ | Historical documentation |
| docker/README.md | Docker reference |
🤝 Contributing
Contributions welcome! Please ensure:
- Architecture principles are maintained
- Tests pass and coverage doesn't decrease
- Documentation is updated
- Commits follow the project style
📄 License
MIT © Riccardo Agnoletto — see ADR-2026-07-06-repository-license.
Projects generated with create-node-ddd-app are yours: no attribution or license obligation attaches to scaffolded output.