Files
halobestie-clone/mitra_app/BUILD_FLAVORS.md
Ramadhan Sjamsani 22743c81e1 feat(build): add dev/staging/prod flavors for client_app + mitra_app
Android product flavors (.dev/.staging suffixes, prod clean) + per-flavor
Dart entrypoints, dart-define env files, and per-flavor Firebase config for
both platforms across 3 projects (halobestie-clone-dev / my-bestie-876ec /
my-bestie-production).

- Android: flavorDimensions("env") + productFlavors; @string/app_name label;
  per-flavor src/<flavor>/google-services.json (clients verified to match each
  applicationId).
- iOS: customer app re-based to the EXISTING App Store identity
  com.asc.hallobestie (dev/staging suffix it; ships as an update to the live
  app). mitra is a new app (com.mybestie.mitra). Per-flavor plists staged in
  ios/config/<flavor>/; Xcode scheme wiring deferred (Mac follow-up).
- firebase_options_{dev,staging,prod}.dart filled with real android + iOS
  values (regenerated from the native config files).
- BUILD_FLAVORS.md per app documents flavor table, build commands, iOS
  identity decision, and the remaining iOS Xcode steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 22:21:50 +08:00

6.4 KiB

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)

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

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)

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_<flavor>.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_<flavor>.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/<flavor>/google-services.json — all 3, client matches the flavor applicationId.
  • ios/config/<flavor>/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

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/<flavor>/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)