app-config
SKILL.md
Flavor Architecture
- Define three flavors:
dev,staging,prod - Use a single
main.dartentry point for all flavors - Pass flavor-specific configuration via
--dart-define-from-file:flutter run --flavor dev --dart-define-from-file=config/dev.json flutter run --flavor staging --dart-define-from-file=config/staging.json flutter run --flavor prod --dart-define-from-file=config/prod.json - NEVER create separate
main_dev.dart,main_staging.dart,main_prod.dartentry points
Config JSON Structure
- Store per-flavor JSON config files in a
config/directory at project root:config/ ├── dev.json ├── staging.json └── prod.json - Example
config/dev.json:{ "FLAVOR": "dev", "BASE_URL": "https://api-dev.example.com", "APP_NAME": "MyApp Dev", "ENABLE_LOGGING": "true", "ENABLE_CRASHLYTICS": "false" } - NEVER put secrets (API keys, signing credentials) in these JSON files — use CI-injected env vars or
flutter_secure_storage - Add
config/*.jsonto.gitignoreif they contain any environment-specific secrets; otherwise commit them for team convenience
Entry Point Pattern
// lib/main.dart
void main() {
const flavor = String.fromEnvironment('FLAVOR', defaultValue: 'dev');
AppConfig.init(flavor: Flavor.fromString(flavor));
runApp(const App());
}
- Read all compile-time values via
String.fromEnvironment('KEY')orbool.fromEnvironment('KEY') - Use a sealed
Flavorenum:sealed class Flavor { dev, staging, prod } AppConfigis a singleton holding flavor, base URL, feature flags, and Firebase config
Environment Configuration
- Store per-flavor config in a centralized
AppConfigclass:baseUrl— API endpoint per environmentenableLogging— verbose logging for dev onlyenableCrashlytics— disabled in devappName— display name per flavor (e.g., "MyApp Dev", "MyApp")
- All values come from the JSON file via
--dart-define-from-file— NO hardcoded per-flavor logic in Dart code - NEVER put secrets in the JSON config files — use
flutter_secure_storageor CI-injected env vars
Platform-Specific Flavor Setup
Android
- Define
flavorDimensionsandproductFlavorsinandroid/app/build.gradle:flavorDimensions "environment" productFlavors { dev { dimension "environment"; applicationIdSuffix ".dev"; resValue "string", "app_name", "MyApp Dev" } staging { dimension "environment"; applicationIdSuffix ".staging"; resValue "string", "app_name", "MyApp Staging" } prod { dimension "environment"; resValue "string", "app_name", "MyApp" } }
iOS
- Create Xcode schemes for each flavor (Dev, Staging, Prod)
- Use xcconfig files for per-flavor bundle ID, display name, and signing
- Map Flutter flavors to Xcode schemes in
ios/Runner.xcodeproj
Firebase Per-Flavor
- Use separate Firebase projects per flavor (dev, staging, prod)
- Place
google-services.json(Android) andGoogleService-Info.plist(iOS) in flavor-specific directories - Use
flutterfire configurewith--projectflag for each environment
Build Commands
# Development
flutter run --flavor dev --dart-define-from-file=config/dev.json
# Staging
flutter run --flavor staging --dart-define-from-file=config/staging.json
# Production release
flutter build appbundle --flavor prod --dart-define-from-file=config/prod.json --release
flutter build ipa --flavor prod --dart-define-from-file=config/prod.json --release
Rules
- NEVER hardcode environment-specific values (URLs, API keys, feature flags)
- NEVER commit production secrets to the repository
- Every team member MUST be able to run any flavor locally with a single command
- CI/CD pipelines MUST specify both
--flavorand--dart-define-from-fileexplicitly - Use a single
main.dart— NEVER create separate entry points per flavor
Weekly Installs
4
Repository
dhruvanbhalara/skillsGitHub Stars
14
First Seen
11 days ago
Security Audits
Installed on
opencode4
gemini-cli4
antigravity4
claude-code4
github-copilot4
amp4