# Build Flavors — mitra_app (Android) The mitra_app has three Android build flavors: **dev**, **staging**, **prod**. Each has its own `applicationId`, backend URL, app display name, Dart entrypoint, Firebase Dart options, and `google-services.json` source set — so all three can be installed side-by-side on one device. > Scope note: this is **Android + Dart + env-files** only. iOS Xcode schemes are > a separate follow-up and are NOT set up yet. ## Flavor matrix | Flavor | applicationId | API_BASE_URL | App name | Entrypoint | env file | |---------|-----------------------------|-------------------------------------------|---------------------------|-----------------------|-------------------| | dev | `com.mybestie.mitra.dev` | `http://192.168.88.247:3000` | Mitra HaloBestie Dev | `lib/main_dev.dart` | `env/dev.json` | | staging | `com.mybestie.mitra.staging`| `https://staging-api.halobestie.com` ⚠️ | Mitra HaloBestie Staging | `lib/main_staging.dart`| `env/staging.json`| | prod | `com.mybestie.mitra` | `https://api.halobestie.com` | Mitra HaloBestie | `lib/main_prod.dart` | `env/prod.json` | ⚠️ The staging `API_BASE_URL` is a **placeholder** — confirm the real staging host and update `env/staging.json` + `lib/firebase/firebase_options_staging.dart`. The `applicationId` suffix is applied in `android/app/build.gradle.kts` (`applicationIdSuffix = ".dev"` / `".staging"`; prod has none). The app name is emitted per flavor via `resValue("string", "app_name", "...")` and read by `android/app/src/main/AndroidManifest.xml` through `android:label="@string/app_name"`. ## Build / run commands Every command MUST pass `--flavor`, a matching `-t` entrypoint, and `--dart-define-from-file` for the env. Examples: ### Run (debug, on a device/emulator) ```bash flutter run --flavor dev -t lib/main_dev.dart --dart-define-from-file=env/dev.json flutter run --flavor staging -t lib/main_staging.dart --dart-define-from-file=env/staging.json flutter run --flavor prod -t lib/main_prod.dart --dart-define-from-file=env/prod.json ``` ### Build APK ```bash flutter build apk --flavor dev -t lib/main_dev.dart --dart-define-from-file=env/dev.json flutter build apk --flavor staging -t lib/main_staging.dart --dart-define-from-file=env/staging.json flutter build apk --flavor prod -t lib/main_prod.dart --dart-define-from-file=env/prod.json ``` ### Build App Bundle (Play Store) ```bash flutter build appbundle --flavor prod -t lib/main_prod.dart --dart-define-from-file=env/prod.json ``` A bare `flutter run` (no `-t`) still works — `lib/main.dart` delegates to the dev bootstrap — but it builds with no flavor selected on Android, so prefer the explicit commands above. ## ⚠️ CRITICAL warnings 1. **`--flavor` is now mandatory for builds.** Once product flavors exist, a bare `flutter build apk` (without `--flavor`) FAILS with a Gradle error (no default flavor). Every build/run command must specify `--flavor` and the matching `-t lib/main_.dart` entrypoint. 2. **The dev applicationId changed to `com.mybestie.mitra.dev`.** Any tooling that references the old package id must be updated when running the dev flavor: - `adb` commands: `adb shell pm clear com.mybestie.mitra.dev`, `adb shell am start ... com.mybestie.mitra.dev/...`, etc. - Maestro flows: `appId: com.mybestie.mitra.dev`. - Any deeplink / FCM tooling keyed on the package name. Prod keeps `com.mybestie.mitra`; staging is `com.mybestie.mitra.staging`. ## Firebase config — STATUS: configured ✅ (2026-06-04) Firebase init is **Dart-side** (`Firebase.initializeApp(options:)` in `lib/bootstrap.dart`), driven by the per-flavor `lib/firebase/firebase_options_.dart`. The mitra app is a **brand-new app** on both platforms (no legacy App Store identity), so the iOS bundle base is `com.mybestie.mitra` — unlike the customer app, which inherits `com.asc.hallobestie`. All apps registered + config in place across 3 projects (one per env): | Env | Firebase project | Android applicationId | iOS bundle ID | |---------|------------------------|-------------------------------|------------------------------| | dev | `halobestie-clone-dev` | `com.mybestie.mitra.dev` | `com.mybestie.mitra.dev` | | staging | `my-bestie-876ec` | `com.mybestie.mitra.staging` | `com.mybestie.mitra.staging` | | prod | `my-bestie-production` | `com.mybestie.mitra` | `com.mybestie.mitra` | In place and verified: - `android/app/src//google-services.json` — all 3, client matches the flavor applicationId. - `ios/config//GoogleService-Info.plist` — all 3, bundle IDs verified. - `lib/firebase/firebase_options_{dev,staging,prod}.dart` — real android + iOS values, no placeholders. ### Regenerating after any ID / key change ```bash flutterfire configure --project=halobestie-clone-dev --out=lib/firebase/firebase_options_dev.dart flutterfire configure --project=my-bestie-876ec --out=lib/firebase/firebase_options_staging.dart flutterfire configure --project=my-bestie-production --out=lib/firebase/firebase_options_prod.dart ``` ### Still TODO — iOS only (Mac/Xcode) - [ ] iOS Xcode schemes + build-phase copy script to select the right `GoogleService-Info.plist` per flavor (until then iOS bundles only `ios/Runner/GoogleService-Info.plist`). See `ios/config/README.md`. > The Google Services Gradle plugin is **not** applied in this app — Android > Firebase init is Dart-side. The `src//google-services.json` files are > laid out for if/when that plugin is added. ## File map | File | Purpose | |---|---| | `android/app/build.gradle.kts` | `flavorDimensions "env"` + `productFlavors` (id suffix + app_name) | | `android/app/src/main/AndroidManifest.xml` | `android:label="@string/app_name"` | | `android/app/src/dev/google-services.json` | dev Firebase config | | `android/app/src/{staging,prod}/google-services.json.README` | placeholders — drop real json here | | `lib/bootstrap.dart` | shared `bootstrap()` + `App` widget | | `lib/main.dart` | bare entrypoint → delegates to dev | | `lib/main_{dev,staging,prod}.dart` | per-flavor entrypoints | | `lib/firebase/firebase_options_{dev,staging,prod}.dart` | per-flavor Dart Firebase options | | `env/{dev,staging,prod}.json` | dart-define values (`API_BASE_URL`, `FLAVOR`) |