Production-ready TypeScript boilerplate.
Nebula ships with authentication, observability, background infrastructure, and developer tooling pre-wired, so you can skip the setup grind and start building features on day one.
| Layer | Technology |
|---|---|
| Language | TypeScript |
| Runtime | Node.js |
| Framework | Express |
| Database | PostgreSQL |
| ORM | Drizzle |
| Cache / Queue / Sessions | Redis |
| Validation | Zod |
| Auth | JWT + Cookies + Google OAuth |
| Email Delivery | Resend + @repo/emails (react-email) |
| SMS | Twilio |
| 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()
@repo/emails ships with 4 pre-built react-email templates, designed off real Dribbble references - not the usual bare-bones "Welcome to X" placeholder. Ready to send from day one:
pnpm install
For local, non-Docker development:
cp .env.example .env
For Docker-based local/production-like setup, create a Docker environment file:
cp .env.example .env.production.local
Important: The Docker Compose setup reads
./.env.production.localfor the app service (env_file: ./.env.production.local).
pnpm dev
This starts the app with tsx --watch ./src/index.ts and listens on the configured PORT value from .env (default: 3000).
Build the app:
pnpm build
Run the compiled server:
PORT=3000 node dist/index.mjs
Or, with a .env file loaded automatically from your shell environment:
node dist/index.mjs
Start the full stack (API + Postgres + Redis + RedisInsight + Prometheus + Grafana + Loki):
docker compose up --build
Run in detached mode:
docker compose up -d
Stop everything:
docker compose down
Copy the example environment file and configure your secrets:
cp .env.example .env
Key values include:
| Variable | Purpose |
|---|---|
PORT |
App server port |
NODE_ENV |
Runtime environment |
DATABASE_URL |
PostgreSQL connection string |
REDIS_HOST / REDIS_PORT |
Redis connection |
JWT_ACCESS_TOKEN_SECRET |
JWT access token signing secret |
JWT_REFRESH_TOKEN_SECRET |
JWT refresh token signing secret |
RESEND_API_KEY |
Email delivery via Resend |
GOOGLE_CLIENT_ID |
Google OAuth |
GOOGLE_CLIENT_SECRET |
Google OAuth |
GOOGLE_AUTH_REDIRECT_URI |
Google OAuth redirect |
TWILIO_ACCOUNT_SID |
SMS via Twilio |
TWILIO_AUTH_TOKEN |
SMS via Twilio |
Generate Drizzle schema artifacts:
pnpm db:generate
Apply migrations:
pnpm db:migrate
Push schema directly:
pnpm db:push
Seed data:
pnpm db:seed
pnpm test
pnpm check:types
pnpm check:lint
terraform/ folder, run:cd terraform
terraform init
terraform plan
terraform apply -auto-approve
Note: 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
pnpm --filter emails run build:package
cp .env.example .env
pnpm dev
Shortest path to the full Docker stack:
cp .env.example .env.production.local
docker compose up