Skip to content

Onboarding (day 1)

You have just been given access to this repo. This page is the shortest path from a clone to a merged PR; everything on it links to the page that owns the detail. Setup that only one person ever does — accounts, credentials, GitHub settings — is not here, it is the owner checklist.

Get the app running

  1. Clone and install. bun install — Bun only; a preinstall guard rejects npm / yarn / pnpm, and bun.lock is the only lockfile (Conventions → Toolchain).
  2. Check your toolchain. bun run doctor prints every tool the lanes need, the version found, the version expected and a fix hint for each. It exits 1 only on a missing required tool (Bun / Node / git), so warnings about Maestro, Xcode or the Android SDK are fine until you work that lane (Toolchain check).
  3. Get added to the EAS project. Ask the owner to invite your Expo account to the organisation that owns the project (expo.dev → account → Members), then bun run eas login. Without it the next two steps fail with a permissions error (Environments and secrets).
  4. Pull the environment. bun run env:pull writes .env.local from the EAS development environment. Never hand-edit it — EAS is the source of truth, and bun run env:check validates what you have against the Zod schema (Environments and secrets → EAS environment variables).
  5. Install the dev client. The app uses native modules, so Expo Go will not run it. Take the latest development build from expo.dev (or an install link posted in Slack) and install it with Expo Orbit — on iOS your device has to be registered first (Device onboarding). A simulator / emulator needs no registration.
  6. Start it. bun run ios (or android / web) starts the dev server against that build, with Rozenite DevTools on.

Make a change and ship it

  1. Branch off main and make the change. The rules that lint and hooks enforce — testID on every pressable, strings through t(), env through @/lib/env, no ios/ or android/ folders — are in Conventions; the full script list with flags is Commands.
  2. Run the gate locally before you push: bun run lint && bun run typecheck && bun run test && bun run knip && bun run format:check && bun run i18n:check. Lefthook runs the fast half on commit and the slow half on push anyway (Conventions → Hooks).
  3. Commit in Conventional Commits. feat: / fix: / chore: …, lowercase subject — commitlint checks the message, and the same config checks your PR title, because the squash merge uses it (Conventions → Commits and PR titles).
  4. Open the PR with ## Summary, ## Test plan and Closes #n (the template prefills them). One ticket, one PR, squash-merged as soon as it is green.

What the checks mean

CheckRunsRead
CI jobsLint, typecheck, unit, knip, format, commitlint, secret scan, bundle budgets, Maestro web, docs build — all requiredJS gate
E2E (native)Maestro flows on iOS + Android, from a fingerprint-matched build repacked with your JSNative E2E
Perf (Reassure)Render-perf compare against the base commit; informationalRender-perf tests
Fingerprint driftComments when your change alters the native fingerprint; informational, but it means a new build is needed before the next production promotionRelease ladder → Fingerprint drift
Preview webDeploys the web build to a pr-N alias and comments the URLRelease ladder → PR previews

Every job in both systems, what triggers it and what to do when one is red: CI overview. A Maestro flow that fails then passes on retry is not yours to delete — file it against the flake budget.

After the merge

Your commit is on staging within a few minutes of the squash merge, as an OTA update. UAT and production are manual, approval-gated republishes of that same update group, and store builds come from a vX.Y.Z tag that release-please pushes. The whole runbook, including rollback and hotfix: Release ladder.