Skip to content

Run: mobile on iOS simulator against DEPLOYED APIs

Run the Flutter app on an iOS simulator pointed at the deployed backend (no local stack needed) and drive/verify it with Maestro. This is the runbook for “run the app on the sim”, “screenshot the app”, or “verify this change on device” without standing up local services.

For Claude: the flutter run goes in a background process and stays attached. Drive the UI with the Maestro MCP tools. Take screenshots to verify. Use .env.prod dart-defines (the app red-screens without them).

Terminal window
xcrun simctl list devices booted # or: available

Or via Maestro: mcp__maestro__list_devices. Don’t reuse a sim another chat is using (e.g. a Builder-E2E device) — pick a free iPhone 17-class sim and note its UDID.

2. Run (background, attached) — prod dart-defines

Section titled “2. Run (background, attached) — prod dart-defines”
Terminal window
cd apps/mobile
fvm flutter run --dart-define-from-file=.env.prod -d <SIM_UDID>

.env.prod carries SUPABASE_URL / SUPABASE_ANON_KEY / API_BASE_URL (pointing at api-treeper.itssatya.in). Without them the app red-screens (Supabase not initialised).

Wait for the launch marker in the run log: Flutter run key commands (and 0 EXCEPTION lines). A Could not build / Error launching means a compile error — grep the log for …​.dart:<n>.*Error.

Compile check matters: dart analyze can miss const-evaluation errors (e.g. const wrapping a theme-token getter). The flutter run/build is the authoritative check.

A freshly-built debug app won’t stay foreground when launched detached — launch it through Maestro and wait for it to settle:

mcp__maestro__launch_app appId=in.itssatya.treeper.app device_id=<SIM_UDID>

Then wait for boot:

Terminal window
until xcrun simctl spawn <SIM_UDID> launchctl list 2>/dev/null | grep -q treeper; do sleep 1; done; sleep 7

Navigate via mcp__maestro__tap_on using accessibility text (native tab bar / map are platform views, not Flutter widgets):

  • Bottom nav: show map · suitcase.fill · home/house.fill · bookmark · notifications/bell.fill
  • Headers: Profile, Add to trip, Import, etc.

Screenshot: mcp__maestro__take_screenshot device_id=<SIM_UDID>.

The attached flutter run does not auto hot-reload (no DTD link for a nohup’d run). To apply edits, re-run (kill the existing run for that sim, start a new one). A debug build also can’t run standalone via simctl launch — it needs its flutter run host, so always relaunch via a fresh flutter run.

Terminal window
pid=$(pgrep -f "flutter run.*<SIM_UDID>" | head -1); [ -n "$pid" ] && kill "$pid"; sleep 2
# …then step 2 again
  • Session may show “Unauthorized” if the sim’s Supabase session expired — the app loads but trip data 401s. Re-login is needed; don’t enter credentials yourself (prohibited) — ask the user, or use a sim that’s already signed in.
  • Map tiles occasionally log a transient Connection refused to cartocdn.com — cosmetic, non-fatal.
  • Theme choice persists across launches (shared_preferences) — the app comes back up in whatever light/dark you last set.
  • Verify the share intent without a real share: Profile → Developer → Test reel share sheet (debug builds only).

For a fully-local backend instead, follow RUN_LOCAL.md.