Skip to content

luksow/madrileno

Repository files navigation

madrileno

A Scala 3 backend template. Wine auctions are the showcase domain.

If you're using this as a template, run the rename script first — it swaps madrileno for your project name + package and removes the auction demo:

./scripts/init-project.scala <project-name>

See docs/scripts.md for what it does and what else lives under scripts/.

Quick start

You'll need four tools. Install each from its package manager or official installer:

The three JVM tools also install together via SDKMAN:

sdk install java 21-tem
sdk install sbt
sdk install scalacli

1. Boot the dev stack

docker compose up -d

That brings up four services on non-standard host ports so they don't clash with anything you already have running:

Service Image Host port(s) Login
Postgres postgres:latest 55432 → 5432 postgres / postgres
Mailpit axllent/mailpit:latest 51025 (SMTP), 58025 (UI)
OpenObserve public.ecr.aws/zinclabs/openobserve:latest 55080 (UI + OTLP HTTP) root@example.com / Complexpass#123
MinIO minio/minio:RELEASE.2024-11-07T00-52-20Z 59000 (S3 API), 59001 (Console UI) minioadmin / minioadmin

State persists across restarts in named volumes. To wipe and start clean:

docker compose down -v
docker compose up -d

2. Configure env

cp .env.sample .env

The sample is wired against the docker-compose ports above — including a working Authorization header for OpenObserve so OTLP traces show up in the UI immediately.

JWT_SECRET is fine as-is for local dev — change it when you don't want strangers to be able to forge tokens. External auth providers (FIREBASE_PROJECT_ID, OIDC_*) ship empty; the app boots fine without them and the dev login (POST /v1/auth/dev) is enabled by default via DEV_AUTH_ENABLED=true.

3. Apply database migrations

sbt "runMain madrileno.main.MigrateMain"

MigrateMain is the app's own IOApp — same as bin/migrate-main in the Docker image — so it reads application.conf with .env injected by sbt-dotenv. Works out of the box on the default .env. It takes a subcommand (migrate is the default):

sbt "runMain madrileno.main.MigrateMain info"       # list applied / pending migrations
sbt "runMain madrileno.main.MigrateMain validate"   # verify checksums match the files
sbt "runMain madrileno.main.MigrateMain clean"      # DROP every table — dev DB only

Run migrate every time you add one under src/main/resources/db/migration/.

4. Run the app

The recommended workflow is one long-lived sbt session in interactive mode:

sbt

Inside the sbt shell:

> ~reStart

~reStart watches sources and restarts the app on every save (compile-on-save). Plain reStart runs it once. The app comes up on http://localhost:9000 (override with PORT in .env).

Quick smoke test from another terminal:

curl http://localhost:9000/v1/health-check

To check the whole setup at once — Docker, the compose services, Postgres, and the app — run the doctor (needs scala-cli):

./scripts/doctor.scala

5. Look around

Things that catch people out

  • sbt caches .env at JVM startup. If you change .env, exit sbt and start it again. Same goes for the long-lived sbt server (~/.sbt/1.0/server/...).
  • docker compose down keeps volumes; docker compose down -v wipes them. Wipe when you want a clean PG, change OpenObserve credentials, or cycle a corrupted state.
  • Tests don't use the docker-compose stack. Testcontainers spins up its own. Don't worry about polluting your dev DB during a test run.
  • Migrations don't run automatically when the app starts. Run sbt "runMain madrileno.main.MigrateMain" after adding one or after wiping volumes.
  • OpenObserve creates OTLP streams on first ingest. If the Traces tab is empty right after boot, hit the app a few times, refresh, give it a moment.

Documentation

Reference material lives in docs/. For day one, read in this order:

Driving development with an AI assistant? docs/ai-assisted-dev.md covers the Metals + madrileno MCP server setup (the build tools CLAUDE.md assumes).

The docs/README.md lists everything else by topic — stack (auth, scheduler, observability…), conventions (domain modeling, sealed monad, error handling), operations (configuration, deployment).

About

A Scala 3 backend template - http4s + Skunk + cats-effect, with a wine-auction module as the worked example.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages