Production-ready TypeScript boilerplate.
Nebula ships with a Postgres + Redis + Drizzle stack, observability, and developer tooling pre-wired, so you can skip the setup grind and start building features on day one. This is the empty variant - no auth, email, or SMS modules included, just the core plumbing.
- Stack Overview
- Dependency Injection Container
- Getting Started
- Environment Setup
- Database Commands
- Testing & Validation
- Monitoring
- Port Map
- Quick Start Summary
| Layer | Technology |
|---|---|
| Language | TypeScript |
| Runtime | Node.js |
| Framework | Express |
| Database | PostgreSQL |
| ORM | Drizzle |
| Cache / Queue / Sessions | Redis |
| Validation | Zod |
| Logging | Pino + request logger middleware, Winston (for Loki) |
| Rate Limiting | express-rate-limit + Redis-backed store |
| Testing | Vitest + Supertest |
| Dev Tooling | Husky, Commitlint, Prettier, ESLint |
| Containers | Docker + Docker Compose |
| Monitoring | Prometheus + Grafana + Loki |
The project uses a central container to wire application dependencies together:
createContainer()
createServices()
createRepositories()
createValidators()
createMiddlewares()
createControllers()
pnpm installFor local, non-Docker development:
cp .env.example .envFor Docker-based local/production-like setup, create a Docker environment file:
cp .env.example .env.production.localImportant: The Docker Compose setup reads
./.env.production.localfor the app service (env_file: ./.env.production.local).
pnpm devThis starts the app with tsx --watch ./src/index.ts and listens on the configured PORT value from .env (default: 3000).
Build the app:
pnpm buildRun the compiled server:
PORT=3000 node dist/index.mjsOr, with a .env file loaded automatically from your shell environment:
node dist/index.mjsStart the full stack (API + Postgres + Redis + RedisInsight + Prometheus + Grafana + Loki):
docker compose up --buildRun in detached mode:
docker compose up -dStop everything:
docker compose downCopy the example environment file and configure your secrets:
cp .env.example .envKey values include:
PORT=3000
NODE_ENV=development
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres"
# DATABASE_URL="postgresql://postgres:postgres@nebula-postgres:5432/postgres" #docker-compose
REDIS_USERNAME=default
REDIS_PASSWORD=default
REDIS_HOST=localhost
# REDIS_HOST=nebula-redis-server #docker-compose
REDIS_PORT=6379| Variable | Purpose |
|---|---|
PORT |
App server port |
NODE_ENV |
Runtime environment |
DATABASE_URL |
PostgreSQL connection string |
REDIS_USERNAME |
Redis auth username |
REDIS_PASSWORD |
Redis auth password |
REDIS_HOST |
Redis connection host |
REDIS_PORT |
Redis connection port |
Generate Drizzle schema artifacts:
pnpm db:generateApply migrations:
pnpm db:migratePush schema directly:
pnpm db:pushSeed data:
pnpm db:seedpnpm test
pnpm check:types
pnpm check:lint- Ensure Grafana, Prometheus, and Loki are running — Docker Compose brings them up on the ports listed below.
- From the
terraform/folder, run:
cd terraform
terraform init
terraform plan
terraform apply -auto-approveNote: The Terraform provider used is the Grafana provider, and the modules rely on JSON dashboard templates in the repo. Terraform creates the dashboard resources in the target Grafana instance.
This boilerplate wires Prometheus and Grafana together, so you get metrics and logs out of the box when running the Docker stack.
Default Docker Compose UI ports:
| Service | URL | Notes |
|---|---|---|
| Grafana | http://localhost:3005 | Dashboards created by Terraform live here. Default credentials: admin:admin (included Docker image) |
| Prometheus | http://localhost:9090 | Explore metrics, run ad-hoc queries |
| Loki | http://localhost:3100 | Log aggregation |
| RedisInsight | http://localhost:5540 | Inspect Redis data |
| Service | Address |
|---|---|
| App server | http://localhost:3000 |
| ↳ Health check | http://localhost:3000/health |
| ↳ Metrics | http://localhost:3000/metrics |
| PostgreSQL | localhost:5432 |
| Redis | localhost:6379 |
| RedisInsight | http://localhost:5540 |
| Prometheus | http://localhost:9090 |
| Grafana | http://localhost:3005 |
| Loki | http://localhost:3100 |
Shortest path to running the project locally:
pnpm install
cp .env.example .env
pnpm devShortest path to the full Docker stack:
cp .env.example .env.production.local
docker compose up