Functional Scala 3 backend + Angular 18 frontend, set up as a single SBT project. Uses Cats, cats-effect, http4s, Doobie, log4cats (JSON), Flyway, and TestContainers. Angular builds to static assets served by the backend in production; during development the Angular dev server proxies to the backend.
- Idiomatic FP backend (cats-effect + http4s)
- Postgres via Doobie + Flyway migrations
- JSON logging (log4cats + Logback)
- JWT auth (signup, login, me)
- Angular dev proxy (BACKEND_HOST/BACKEND_PORT)
- Heroku-ready (
sbt stage, Procfile, Postgres) - TestContainers for DB integration tests
- Scala 3, SBT, cats-effect, http4s, circe, Doobie, Flyway, log4cats
- Angular 18, RxJS 7, Node 22 LTS
- JDK 21+
- SBT
- Node.js 22.x (see
.nvmrconce created) - Docker (for TestContainers parity locally optional)
- One-command workflow (backend + Angular dev proxy):
ANGULAR_MODE=dev sbt run- Starts the Scala API on
http://localhost:8080 - Boots the Angular dev server on
http://localhost:4200with the proxy already configured
- Starts the Scala API on
- Manual alternative:
- Backend:
sbt run - Frontend:
npm --prefix ui install && npm --prefix ui start- Ensure
BACKEND_HOST=localhost BACKEND_PORT=8080
- Ensure
- Backend:
Health and readiness:
GET http://localhost:8080/healthGET http://localhost:8080/ready
- Build Angular assets & run backend with a single command:
ANGULAR_MODE=prod sbt run- Runs
npm ci+npm run build:prod(output tosrc/main/resources/static) before starting the API
- Runs
- Build and stage for deployment:
sbt stagetarget/universal/stage/bin/<app> -Dhttp.port=8080
Alternatively, if using assembly:
sbt assemblyjava -Dhttp.port=8080 -jar target/scala-*/<app>-assembly-*.jar
Environment variables (see docs/requirements.md for full list):
HTTP_PORT(default 8080)ANGULAR_MODE(dev|prod; defaults todev)ANGULAR_PORT(default 4200)BACKEND_HOST,BACKEND_PORT(dev proxy target)DATABASE_URL(Heroku-style JDBC string)DB_USER,DB_PASSWORD,DB_SCHEMA(override defaults when not usingDATABASE_URL)DB_MAX_POOL_SIZE,DB_MIN_IDLE,DB_CONNECTION_TIMEOUT(Hikari tuning)JWT_SECRET,JWT_TTL(finite duration, default7d)TODO_DEFAULT_PAGE_SIZE,TODO_MAX_PAGE_SIZELOG_LEVEL(JSON logs)EMAIL_PROVIDER,EMAIL_FROM_ADDRESS,EMAIL_API_KEY,EMAIL_RESET_SUBJECT,EMAIL_ACTIVATION_SUBJECT,EMAIL_ACTIVATION_URL_BASEPASSWORD_RESET_URL_BASE,PASSWORD_RESET_TOKEN_TTL,ACTIVATION_TOKEN_TTLTRACING_ENABLED(optional natchez scaffold)
- Backend unit/integration:
sbt test - Frontend unit:
npm --prefix ui test - End-to-end smoke (requires API running locally):
scripts/smoke.sh- Provide
SMOKE_EMAIL/SMOKE_PASSWORDfor an activated test account:SMOKE_EMAIL=user@example.com SMOKE_PASSWORD=secret scripts/smoke.sh
- Provide
- Pre-push helper (formats, tests, lints, builds):
scripts/pre-push.sh
- Logs are JSON (Logstash encoder) with per-request
requestId, optionaluserId, and latency metrics. - Enable verbose logging by adjusting
LOG_LEVEL; request ids propagate viaX-Request-Idheader. - Optional tracing scaffold (
natchez) is disabled by default; setTRACING_ENABLED=trueand swap the entrypoint incom.example.app.tracing.Tracingwhen wiring Jaeger/OTLP/etc.
- Buildpacks (set in this order):
heroku/nodejs(builds the Angular UI duringsbt stage)heroku/java
heroku buildpacks:set heroku/nodejs heroku buildpacks:add --index 2 heroku/java
sbt stageis invoked during slug build; the committedProcfileruns the staged binary:web: target/universal/stage/bin/scala-angular-cats-template -Dhttp.port=$PORT
- Recommended config vars (examples):
Config var Purpose Example value ANGULAR_MODEServe pre-built UI (disables dev proxy) prodJWT_SECRETSigning key for auth tokens super-secret-change-meLOG_LEVELRuntime log level (JSON format) INFOTRACING_ENABLEDEnable natchez middleware (optional) falseDATABASE_URLProvided by Heroku Postgres add-on (auto-set by Heroku) - Postgres: connection details arrive via
DATABASE_URL; SSL is auto-detected (sslmode=requirewhen present).
- Backend:
src/main/scala,src/main/resources(Flyway migrations, Logback, static in prod) - Frontend:
ui/(Angular),ui/src/proxy.conf.jsfor dev proxy - CI:
.github/workflows/ci.yml - Docs:
docs/requirements.md,docs/design.md,docs/tech.md,docs/tasks.md,docs/runbook.md - Collaboration:
AGENTS.md
- Requirements:
docs/requirements.md - Design:
docs/design.md - Technical decisions:
docs/tech.md - Tasks and milestones:
docs/tasks.md - On-call runbook:
docs/runbook.md
- See
AGENTS.mdfor branching, PRs, and conflict resolution.