This guide gets the full FinWatch stack running locally.
| Tool | Version | Notes |
|---|---|---|
| Docker | 24+ | With Compose v2 (docker compose, not docker-compose). |
| Go | 1.26 | For running the backend/tests outside Docker. |
| Node | 24 | With npm 11, for the frontend outside Docker. |
| Make | any | Task runner for the commands below. |
Running
make devonly requires Docker + Compose. Go and Node are needed for running tests/builds directly on the host (e.g.make verify).
cp .env.example .env
make devThis builds and starts three services:
| Service | URL / port | Purpose |
|---|---|---|
| db | localhost:5432 | PostgreSQL (synthetic) |
| api | http://localhost:8080 | Go API |
| web | http://localhost:8081 | React app |
Verify the API:
curl http://localhost:8080/health/live # {"status":"ok"}
curl http://localhost:8080/health/ready # {"status":"ready"} once db is upStop the stack:
make stopBackend:
cd apps/api
go test ./...
go run ./cmd/api # needs DATABASE_URL etc. from your environmentFrontend:
cd apps/web
npm install
npm run dev # Vite dev server on http://localhost:5173Migrations are not applied automatically by the API. Apply them with the
migrate CLI:
migrate -path apps/api/migrations -database "$DATABASE_URL" upSee apps/api/migrations/README.md.
The API does not ingest from any external source; synthetic transactions are generated locally. With the database migrated, ingest a batch:
make seed N=100 # or: cd apps/api && go run ./cmd/api seed -n 100Each insert writes a transaction.observed row to the outbox in the same
database transaction. List the results (most-recent first, cursor-paginated):
curl 'http://localhost:8080/transactions?limit=20'
# follow nextCursor for the next page:
curl 'http://localhost:8080/transactions?limit=20&cursor=<nextCursor>'The store integration tests run only when FINWATCH_TEST_DATABASE_URL points at
a disposable database; otherwise they skip (so make verify stays green without
a DB). Against the local stack:
make dev # Postgres on localhost:5432
FINWATCH_TEST_DATABASE_URL='postgres://finwatch:finwatch_dev_password@localhost:5432/finwatch?sslmode=disable' \
go test ./apps/api/internal/transactions/store/...These tests reset the feature tables and re-apply the migrations themselves. CI runs them automatically against a Postgres service.
Data access is generated from SQL with sqlc (no ORM). After
changing apps/api/queries/*.sql or a migration, regenerate:
make sqlc # requires `sqlc` on PATHThe generated code under apps/api/internal/platform/postgres/db is committed;
make verify does not run sqlc.
Before pushing:
make verify # fmt, vet, lint, type-check, tests, builds
git diff --checkAll configuration is via environment variables (see .env.example) and is
validated at API startup — an invalid value stops the process immediately with a
descriptive error.
docker composenot found — install Docker Compose v2 (bundled with recent Docker Desktop / thedocker-compose-pluginpackage).- API readiness returns 503 — the database is not up yet; wait for the
dbhealth check, then retry. - Port already in use — stop the conflicting process or change the published
ports in
docker-compose.yml.