The fastest path from a fresh clone to a working end-to-end setup (server + mobile app on a phone/emulator on the same LAN). For deeper detail on any single component, see the per-component setup guides linked at each step.
This quickstart covers the minimum golden path: server + mobile app. GSM/SMS fallback and the admin frontend are optional add-ons, covered at the end.
- Docker + Docker Compose v2, Node ≥ 18, pnpm (mobile app's declared package manager — see
mobile-app/sapot-mobile-app/package.json'spackageManagerfield) - Android device or emulator, on the same Wi-Fi network as the machine running the server
- Nix (used to pin the mobile app's dev toolchain)
All three commands run from the repo root, because docker/up.sh lives there, not in server/:
cp server/.env.example server/.env # edit placeholder secrets before anything but local dev
./docker/up.sh up --build -d
docker compose exec api alembic upgrade headThe first two bring up MariaDB, Redis, the API, an Nginx TLS terminator, the admin dashboard, and the tileserver together, with no local MariaDB/Redis install and no manual cert setup, auto-detecting this machine's LAN IP for the dev TLS certificate's SAN.
The third creates the schema. It is a required, separate step: the schema is owned by Alembic (ADR 0007) and nothing in the container runs it for you, so without it the API starts but every database-backed request fails. Re-run it after any pull that adds a migration.
Checkpoint: curl -sk https://<your-lan-ip>/version (or https://localhost/version from the same machine) returns a JSON version payload. If not, see Troubleshooting: server won't start.
Full detail: docker-setup.md. Prefer to run the API directly without Docker? See server-setup.md (bare-metal, requires installing MariaDB/Redis yourself).
# from mobile-app/
bash configure_nix.sh
nix develop -L
cd sapot-mobile-app
pnpm install
cp .env.example .envPoint the app at your server's LAN IP:
# mobile-app/sapot-mobile-app/.env
EXPO_PUBLIC_DEV_HOST=192.168.1.x # same host from step 2pnpm devOpen the app on your device/emulator (same Wi-Fi network as the server), go to the getting-started screen, tap Server Mode, then the cog icon on that card, and enter the same LAN IP.
Checkpoint: the app's login/registration screen loads without a network error. If it hangs or errors, see Troubleshooting: mobile app can't reach the server.
Full detail: mobile-app-setup.md.
- Register a new account in the app. To skip registration entirely, pick LAN Mode on the getting-started screen instead of Server Mode. It asks only for a first and last name and signs you in as a guest, with no server dependency for LAN messaging.
- Repeat step 3 on a second device on the same LAN.
- Discover the peer (automatic via mDNS on the same network) and send a message.
Checkpoint: the message appears on the recipient device. This confirms LAN peer discovery, transport (WebRTC data channel or LAN TCP+TLS), and E2E encryption are all working together.
Only needed if testing SMS delivery to devices off the LAN. See gsm-module-setup.md — requires a serial-attached GSM modem and a shared GSM_SECRET matching the server's.
Step 2's stack already builds and serves the dashboard: open https://<your-lan-ip>/admin (the
/admin prefix is required; the app sets basePath: "/admin"). A fresh database has no admin
account and the dashboard has no signup, so create the first one before you can log in. See
admin-frontend-setup.md.
- architecture/system-overview.md — how the pieces fit together
- TROUBLESHOOTING.md — common setup failures and fixes
- environment-config.md — full environment variable reference