Skip to content

Run: full local stack

Bring up everything locally — Supabase, backend, workers, web — and run the mobile app against the local stack. This is the runbook to follow when asked to “run/start the local dev setup” or “test against local.”

For Claude: each long-running server goes in its own background process (run_in_background: true). Don’t block the shell on them. After starting, poll the health/port to confirm readiness, then move on. Use email/password auth (local has enable_confirmations=false).

Prereqs: supabase CLI, node 20+, uv (Python), fvm (Flutter), Xcode (for the iOS sim).

1. Supabase (run from infra/, NOT the repo root)

Section titled “1. Supabase (run from infra/, NOT the repo root)”
Terminal window
cd infra && supabase start

Ports: API :55321 · DB :55322 · Studio :55323 · Mailpit :55324. Running from the repo root hits a stray 54321 project — always cd infra first. Readiness: curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:55321/auth/v1/health200.

Terminal window
cd apps/backend && npm i && npm run start:dev

Readiness: curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000/v1/health200.

Terminal window
cd apps/workers && uv run uvicorn treeper_workers.main:app --reload

Readiness: curl -s http://127.0.0.1:8000/openapi.json | head -c 50 (lists routes).

Terminal window
cd apps/web && npm i && npm run dev:local # dev:local uses .env.local (local stack)

Plain npm run dev is prod mode by default (.env.prod). Use dev:local for the local stack.

The iOS simulator can reach localhost, so point dart-defines at the local backend (and Supabase):

Terminal window
cd apps/mobile
fvm flutter run --dart-define-from-file=.env.local -d <SIM_UDID>
# …or explicitly:
fvm flutter run -d <SIM_UDID> \
--dart-define API_BASE_URL=http://127.0.0.1:3000/v1 \
--dart-define SUPABASE_URL=http://127.0.0.1:55321 \
--dart-define SUPABASE_ANON_KEY=<local anon key>

Get the simulator UDID: xcrun simctl list devices booted (or available). For a real device, replace 127.0.0.1 with your machine’s LAN IP.

  • SearXNG is internal-only and Nominatim is blocked in the sandbox → geocode + media enrichment won’t fully work locally; verify those on prod.
  • The worker AI/chat web-search needs GEMINI_API_KEY / LITELLM_* in apps/workers/.env to do anything real.
  • Seeding real data locally: see the “sync prod data to local” recipe in the project memory / infra/supabase.

To run the mobile app against the deployed APIs instead (no local backend), follow RUN_SIM_PROD.md.