The app is built with EAS Build. Local native folders come from expo prebuild and are not committed.

Prerequisites

pnpm install applies the four patches in patches/. See Native modules and config plugins.

EAS profiles

eas.json defines three build profiles. Notes:
  • The development profile sets no API URL, so the dev client detects the Metro host. See API client.
  • Both preview and production point at the production API. There is no separate staging backend in this file.
  • preview and production also set EXPO_PUBLIC_FB_APP_ID.
  • cli.appVersionSource is remote: EAS owns the build number.
  • .env.production mirrors the production env block for local production builds. Its header says to keep the two in sync. The file is ignored by Git.
The submit.production block targets the App Store app and the Google Play production track with releaseStatus: completed.

Scripts

Run on a device or simulator

Prebuild

Use the clean variant after removing a plugin option, a permission or an Info.plist key. A normal prebuild does not delete what it no longer manages.

Cloud builds

Build and submit

Signing credentials and store API keys are managed in EAS and are not in the repository. Ask the project owner for access. Do not add key files to the repo. .gitignore already excludes *.p8, *.p12, *.jks, *.key, *.pem and *.mobileprovision.

Local builds

The iOS local scripts prefix PATH with /usr/bin:/bin:/usr/sbin:/sbin so system tools win over any shadowing versions on your path.

iOS specifics

  • Deployment target is iOS 16.4.
  • iPad is not supported (supportsTablet: false).
  • usePrecompiledModules is false in expo-build-properties. Together with the expo-modules-jsi patch, the build compiles that framework from source with its derived data kept under ~/Library/Caches.
  • The build has a second target, ExpoWidgetsTarget, for the home screen widgets and the Live Activity. It is declared under extra.eas.build.experimental.ios.appExtensions with an app group, so EAS provisions it.
  • The app icon has light, dark and tinted variants.
  • Changes to the Live Activity buttons depend on the expo-widgets patch. That patch is native, so it needs a rebuild to take effect.

Android specifics

  • minSdkVersion is 26. Health Connect requires it.
  • Push needs google-services.json, referenced as android.googleServicesFile.
  • predictiveBackGestureEnabled is false.
  • The local module in modules/cardio-notification is compiled into the app.
  • Production output is an app bundle. Preview and development produce an APK you can install directly.

Running on an Android emulator

expo run:android generates android/ if it is missing, builds a debug APK and installs it on a booted emulator. Things that reliably go wrong, from project notes on this machine setup: The first build downloads a lot and takes several minutes. Later builds reuse the Gradle and native caches. Avoid --clean unless you need it. In development the emulator reaches the backend on the host machine through 10.0.2.2:3031, which config.ts selects automatically.

Dev client or Expo Go

The app depends on native modules that Expo Go does not contain: widgets, HealthKit, Health Connect, view capture, sharing and the local cardio module. Use a dev client (pnpm ios or pnpm android, or a development EAS build) for real work. The app is written to still boot without those modules. See Guarding native imports. To run in Expo Go, start Metro with EXPO_GO_SHIMS=1 so expo-widgets is replaced by its shim. After adding a native dependency, rebuild the dev client. Until then the new module is missing from your binary exactly as it would be for a trainee on an old store build.

Release checklist

  1. pnpm typecheck and pnpm lint pass.
  2. Bump version in app.json and package.json.
  3. Confirm eas.json production env and .env.production match.
  4. Build and submit: pnpm testflight and pnpm playstore, or pnpm release.
  5. After the build is live, follow the version bump steps in OTA updates.