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