Getting started
From zero to a signed-in example app with test data. Everything runs locally; the external services (Postgres, MinIO, Hatchet) are containers.
Prerequisites
- Bun — runtime, package manager and script runner (
npm/nodeare not used here) - Docker with compose
Set up
Install the workspace
bun installOne install at the repo root resolves all workspace packages — the Toolkit under
packages/ and the example app.
Configure the environment
cd example
cp .env.example .envThe template doubles as documentation: it shows which services are optional — background jobs, real email delivery and AI light up only when their variables are set. See the environment reference for every variable.
Start the infrastructure
docker compose up -dPostgres, MinIO, Valkey and Hatchet (jobs) start with the default profile — enabling actual job processing is a one-time token setup, see Background jobs → Run it locally.
Everything else is an opt-in profile you start only when you need it:
| Profile | Brings up | Used by |
|---|---|---|
tools | pgweb database browser (:8081) | poking at the DB offline |
monitoring | Prometheus + Grafana (:3001) + Loki | Monitoring |
proxy | Caddy front door (:8088) with security headers | Security & operations |
idp | lldap + Dex (local directory + SSO) | Enterprise sign-in |
realtime | Centrifugo (:8000) for server-push | Realtime |
docker compose --profile monitoring up -d # one example; combine with --profile as neededThe app boots and works without any of them — a missing optional service degrades one feature, never the whole product.
The seed data and accounts
The example app is seeded: bun run db:seed loads a deterministic set of test
data — around a hundred users, workspaces, projects, tasks, comments and attachments
(same faker seed every time, so everyone's local data looks alike). Most projects get
a map position in a Swedish town, so /sandbox/map has markers from the start. The seed is
destructive: it truncates every table before loading.
Every seeded account uses the password password123.
| Account | Who |
|---|---|
admin@example.com | Site admin — the only account that can open /admin |
astrid@example.com | Astrid Lindgren — regular user with projects and tasks (the one most e2e tests use) |
bo@example.com | Bo Karlsson |
cecilia@example.com | Cecilia Hägg |
david@example.com | David Andersson |
eva@example.com | Eva Nilsson |
fredrik@example.com | Fredrik Söderberg |
gabriella@example.com | Gabriella Modig |
henrik@example.com | Henrik Wallin |
ida@example.com | Ida Roos |
jonas@example.com | Jonas Ekberg |
The seed also creates a crowd of background users to make member lists feel real — those have no credentials and cannot sign in.
Three surfaces to know about
| Surface | URL | Purpose |
|---|---|---|
| The app | / | The example app's real UI |
| Sandbox | /sandbox | One harness page per building block — see Sandbox-first. Open in dev; on a deployed site it requires site admin |
| Admin | /admin | The Django-admin replacement — requires site admin |
Verify with the tests
cd example
bun run e2e # the whole Playwright suite
bunx playwright test sandbox # only the building-block tests — seconds to runAnd the gates CI expects green, from the repo root:
bun run typecheck
bun run lint
bun run fmt