Local setup¶
Bootstrap a fresh machine (laptop, ephemeral VM, codespace) to run, test, and deploy Fountain. Should take ~10 minutes on broadband.
Prerequisites¶
| Tool | Why | Install |
|---|---|---|
mise |
Pins Elixir/Erlang to exact versions in .tool-versions |
brew install mise (macOS) or curl https://mise.run | sh (Linux/WSL) |
gh |
GitHub CLI for cloning and PRs | brew install gh && gh auth login |
psql |
Client for dev/test Postgres | Comes with brew install postgresql@16 |
| Docker or native Postgres 14+ | Host the dev/test database | brew install --cask orbstack or brew install postgresql@16 |
After installing mise, activate it in your shell.
1. Clone¶
2. Install the toolchain¶
Reads .tool-versions and installs Erlang/OTP 28 + Elixir 1.19.2. The same pinned versions are used in production.
Verify:
3. Hex + Rebar (one-time per toolchain)¶
4. Postgres¶
Option A - Docker (recommended):
Brings up Postgres 16 on localhost:5432. Stop with docker compose down; data persists in the postgres_data volume.
Option B - Native Postgres:
psql -h localhost -U "$USER" -d postgres \
-c "CREATE ROLE postgres WITH LOGIN SUPERUSER PASSWORD 'postgres'"
Both satisfy the default DATABASE_URL in config/dev.exs and config/test.exs.
5. Dependencies and database¶
mix deps.get
mix setup # dev DB: create + migrate
MIX_ENV=test mix ecto.create
MIX_ENV=test mix ecto.migrate
6. Environment variables¶
Copy .env.example to .env and fill in the blanks:
| Variable | Purpose |
|---|---|
DATABASE_URL |
Postgres connection |
MASTER_SECRETS_KEY |
Platform master key for envelope encryption |
SPRITES_TOKEN |
Sprites sandbox platform token |
GITHUB_OAUTH_CLIENT_ID/SECRET |
GitHub OAuth app |
STRIPE_* |
Billing integration |
RESEND_API_KEY |
Transactional email |
Generate a master key:
7. Run¶
mix phx.server # http://localhost:4000
mix test # full test suite
mix precommit # same checks CI runs
Troubleshooting¶
role "postgres" does not exist- See step 4.- Tests fail with connection pool timeouts - Make sure
config/test.exshaspool_size: 20. miseis slow on first run - Normal; it compiles Erlang from source (~5 min). Cached after.