1---2name: flutter-config3description: Use when configuring build flavors, passing environment variables via dart-define-from-file, or setting up stage-specific credentials.4---5
6# Flavor Architecture
7
8- Define three flavors: `dev`, `staging`, `prod`
9- Use a **single `main.dart`** entry point for all flavors
10- Pass flavor-specific configuration via `--dart-define-from-file`:
11 ```bash
12 flutter run --flavor dev --dart-define-from-file=config/dev.json
13 flutter run --flavor staging --dart-define-from-file=config/staging.json
14 flutter run --flavor prod --dart-define-from-file=config/prod.json
15 ```
16- NEVER create separate `main_dev.dart`, `main_staging.dart`, `main_prod.dart` entry points
17
18# Config JSON Structure
19
20- Store per-flavor JSON config files in a `config/` directory at project root:
21 ```
22 config/
23 ├── dev.json
24 ├── staging.json
25 └── prod.json
26 ```
27- Example `config/dev.json`:
28 ```json
29 {
30 "FLAVOR": "dev",
31 "BASE_URL": "https://api-dev.example.com",
32 "APP_NAME": "MyApp Dev",
33 "ENABLE_LOGGING": "true",
34 "ENABLE_CRASHLYTICS": "false"
35 }
36 ```
37- NEVER put secrets (API keys, signing credentials) in these JSON files: use CI-injected env vars or `flutter_secure_storage`
38- Add `config/*.json` to `.gitignore` if they contain any environment-specific secrets; otherwise commit them for team convenience
39
40# Entry Point Pattern
41
42```dart
43// lib/main.dart
44void main() {
45 const flavor = String.fromEnvironment('FLAVOR', defaultValue: 'dev');
46 AppConfig.init(flavor: Flavor.fromString(flavor));
47 runApp(const App());
48}
49```
50
51- Read all compile-time values via `String.fromEnvironment('KEY')` or `bool.fromEnvironment('KEY')`
52- Use a sealed `Flavor` enum: `sealed class Flavor { dev, staging, prod }`
53- `AppConfig` is a singleton holding flavor, base URL, feature flags, and Firebase config
54
55# Environment Configuration
56
57- Store per-flavor config in a centralized `AppConfig` class:
58 - `baseUrl`: API endpoint per environment
59 - `enableLogging`: verbose logging for dev only
60 - `enableCrashlytics`: disabled in dev
61 - `appName`: display name per flavor (e.g., "MyApp Dev", "MyApp")
62- All values come from the JSON file via `--dart-define-from-file`: NO hardcoded per-flavor logic in Dart code
63- NEVER put secrets in the JSON config files: use `flutter_secure_storage` or CI-injected env vars
64
65# Platform-Specific Flavor Setup
66
67## Android
68
69- Define `flavorDimensions` and `productFlavors` in `android/app/build.gradle`:
70 ```groovy
71 flavorDimensions "environment"
72 productFlavors {
73 dev { dimension "environment"; applicationIdSuffix ".dev"; resValue "string", "app_name", "MyApp Dev" }
74 staging { dimension "environment"; applicationIdSuffix ".staging"; resValue "string", "app_name", "MyApp Staging" }
75 prod { dimension "environment"; resValue "string", "app_name", "MyApp" }
76 }
77 ```
78
79## iOS
80
81- Create Xcode schemes for each flavor (Dev, Staging, Prod).
82- Use xcconfig files for per-flavor bundle ID, display name, and signing.
83- Map Flutter flavors to Xcode schemes in `ios/Runner.xcodeproj`.
84- **Swift Package Manager Integration**: When configuring iOS flavors, Xcode schemes map package dependency configurations automatically. No CocoaPods `Podfile` changes are required for SPM. Ensure all dependency overrides are defined under Package Dependencies inside Xcode Runner project settings.
85
86# Firebase Per-Flavor
87
88- Use separate Firebase projects per flavor (dev, staging, prod)
89- Place `google-services.json` (Android) and `GoogleService-Info.plist` (iOS) in flavor-specific directories
90- Use `flutterfire configure` with `--project` flag for each environment
91
92# Build Commands
93
94```bash
95# Development
96flutter run --flavor dev --dart-define-from-file=config/dev.json
97
98# Staging
99flutter run --flavor staging --dart-define-from-file=config/staging.json
100
101# Production release
102flutter build appbundle --flavor prod --dart-define-from-file=config/prod.json --release
103flutter build ipa --flavor prod --dart-define-from-file=config/prod.json --release
104```
105
106# Rules
107
108- NEVER hardcode environment-specific values (URLs, API keys, feature flags)
109- NEVER commit production secrets to the repository
110- Every team member MUST be able to run any flavor locally with a single command
111- CI/CD pipelines MUST specify both `--flavor` and `--dart-define-from-file` explicitly
112- Use a single `main.dart`: NEVER create separate entry points per flavor