prprompts-flutter-generator
Version:
AI-powered Flutter development with full automation + official extension support - Generate 32 security-audited guides & auto-implement in 2-3 hours. NEW v5.1: Official Claude Code plugin with hooks, Gemini TOML commands, Qwen MCP settings. Features: Comp
974 lines (786 loc) • 26.8 kB
Markdown
# Flutter Flavors Setup Skill - Execution Prompt
## Context
You are executing the **flutter-flavors** skill. This skill sets up complete Flutter flavor configuration for multi-environment development, enabling developers to build different versions of their app (dev, staging, production) with different configurations, API endpoints, app names, and bundle identifiers.
**This skill configures both iOS (Xcode schemes) and Android (build variants) simultaneously.**
## Inputs
- **environments**: {{inputs.environments || ["dev", "staging", "production"]}}
- **app_name_suffix**: {{inputs.app_name_suffix || true}}
- **bundle_id_suffix**: {{inputs.bundle_id_suffix || true}}
- **custom_icons**: {{inputs.custom_icons || false}}
- **environment_config**: {{inputs.environment_config || default_config}}
---
## Prerequisites Check
Before starting, verify:
1. ✅ Flutter project initialized (`pubspec.yaml` exists)
2. ✅ Git repository initialized
3. ✅ Working in project root directory
4. ✅ iOS project exists (`ios/` directory)
5. ✅ Android project exists (`android/` directory)
**If any prerequisite fails:**
```json
{
"error": "Prerequisites not met",
"missing": ["flutter_project"],
"suggestions": [
"Run: flutter create .",
"Ensure you're in project root directory"
]
}
```
---
## Task: Setup Flutter Flavors Configuration
### Phase 1: Android Configuration (Build Variants)
#### Step 1.1: Update android/app/build.gradle
**Location**: `android/app/build.gradle`
**Add productFlavors configuration** (after `defaultConfig` block):
```gradle
android {
// ... existing configuration ...
defaultConfig {
// ... existing defaults ...
}
flavorDimensions "environment"
productFlavors {
{{#each environments}}
{{this}} {
dimension "environment"
{{#if ../bundle_id_suffix}}
{{#if (ne this "production")}}
applicationIdSuffix ".{{this}}"
{{/if}}
{{/if}}
{{#if ../app_name_suffix}}
resValue "string", "app_name", "${project.name} {{capitalize this}}"
{{else}}
resValue "string", "app_name", "${project.name}"
{{/if}}
// Environment-specific configuration
buildConfigField "String", "API_BASE_URL", "\"{{lookup ../environment_config this 'api_url'}}\""
buildConfigField "boolean", "ENABLE_ANALYTICS", "{{lookup ../environment_config this 'enable_analytics'}}"
buildConfigField "boolean", "ENABLE_LOGGING", "{{lookup ../environment_config this 'enable_logging'}}"
}
{{/each}}
}
buildTypes {
debug {
// Debug-specific settings
debuggable true
minifyEnabled false
}
release {
// Release-specific settings
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug // Change for production
}
}
}
```
**Complete example for 3 standard flavors:**
```gradle
android {
namespace 'com.example.myapp'
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.example.myapp"
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
flavorDimensions "environment"
productFlavors {
dev {
dimension "environment"
applicationIdSuffix ".dev"
resValue "string", "app_name", "MyApp Dev"
buildConfigField "String", "API_BASE_URL", "\"https://dev-api.example.com\""
buildConfigField "boolean", "ENABLE_ANALYTICS", "false"
buildConfigField "boolean", "ENABLE_LOGGING", "true"
}
staging {
dimension "environment"
applicationIdSuffix ".staging"
resValue "string", "app_name", "MyApp Staging"
buildConfigField "String", "API_BASE_URL", "\"https://staging-api.example.com\""
buildConfigField "boolean", "ENABLE_ANALYTICS", "true"
buildConfigField "boolean", "ENABLE_LOGGING", "true"
}
production {
dimension "environment"
// No suffix for production - clean bundle ID
resValue "string", "app_name", "MyApp"
buildConfigField "String", "API_BASE_URL", "\"https://api.example.com\""
buildConfigField "boolean", "ENABLE_ANALYTICS", "true"
buildConfigField "boolean", "ENABLE_LOGGING", "false"
}
}
buildTypes {
debug {
debuggable true
minifyEnabled false
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
```
---
#### Step 1.2: Update android/app/src/main/AndroidManifest.xml
**Update app name reference** to use flavor-specific name:
```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="@string/app_name"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<!-- ... rest of manifest ... -->
</application>
</manifest>
```
---
#### Step 1.3: Create flavor-specific resource directories (if custom_icons = true)
```bash
# Create directories for each flavor
mkdir -p android/app/src/dev/res/mipmap-hdpi
mkdir -p android/app/src/dev/res/mipmap-mdpi
mkdir -p android/app/src/dev/res/mipmap-xhdpi
mkdir -p android/app/src/dev/res/mipmap-xxhdpi
mkdir -p android/app/src/dev/res/mipmap-xxxhdpi
# Repeat for staging and production
mkdir -p android/app/src/staging/res/mipmap-hdpi
mkdir -p android/app/src/staging/res/mipmap-mdpi
mkdir -p android/app/src/staging/res/mipmap-xhdpi
mkdir -p android/app/src/staging/res/mipmap-xxhdpi
mkdir -p android/app/src/staging/res/mipmap-xxxhdpi
mkdir -p android/app/src/production/res/mipmap-hdpi
mkdir -p android/app/src/production/res/mipmap-mdpi
mkdir -p android/app/src/production/res/mipmap-xhdpi
mkdir -p android/app/src/production/res/mipmap-xxhdpi
mkdir -p android/app/src/production/res/mipmap-xxxhdpi
```
**Create placeholder README:**
```markdown
# Flavor-Specific Icons
Place your flavor-specific app icons in these directories:
- `dev/res/mipmap-*/` - Development icons (add DEV badge/ribbon)
- `staging/res/mipmap-*/` - Staging icons (add STAGING badge/ribbon)
- `production/res/mipmap-*/` - Production icons (final polished icons)
Use a tool like `flutter_launcher_icons` or manually replace ic_launcher.png files.
```
---
### Phase 2: iOS Configuration (Xcode Schemes)
#### Step 2.1: Create Xcode Build Configurations
**This requires manual Xcode configuration, but we'll generate the commands:**
**Create:** `ios/setup-flavors.sh`
```bash
#!/bin/bash
# Flutter Flavors - iOS Setup Script
# This script provides instructions for setting up Xcode schemes manually
echo "=========================================="
echo "Flutter Flavors - iOS Setup Instructions"
echo "=========================================="
echo ""
echo "Follow these steps in Xcode:"
echo ""
echo "1. Open ios/Runner.xcworkspace in Xcode"
echo ""
echo "2. Create Build Configurations:"
echo " - Click on Runner project"
echo " - Select Info tab"
echo " - Expand 'Configurations'"
echo " - Duplicate Debug → Debug-dev, Debug-staging, Debug-production"
echo " - Duplicate Release → Release-dev, Release-staging, Release-production"
echo ""
echo "3. Create Schemes for each flavor:"
echo " - Product → Scheme → Manage Schemes"
echo " - Duplicate Runner scheme 3 times"
echo " - Rename to: dev, staging, production"
echo ""
echo "4. Configure each scheme:"
echo " - Edit Scheme → Build Configuration"
echo " - dev: Debug-dev (debug), Release-dev (release)"
echo " - staging: Debug-staging (debug), Release-staging (release)"
echo " - production: Debug-production (debug), Release-production (release)"
echo ""
echo "5. Set User-Defined Build Settings:"
echo " - Build Settings → + → Add User-Defined Setting"
echo " - PRODUCT_BUNDLE_IDENTIFIER"
echo " - Debug-dev/Release-dev: com.example.app.dev"
echo " - Debug-staging/Release-staging: com.example.app.staging"
echo " - Debug-production/Release-production: com.example.app"
echo " - DISPLAY_NAME"
echo " - Debug-dev/Release-dev: MyApp Dev"
echo " - Debug-staging/Release-staging: MyApp Staging"
echo " - Debug-production/Release-production: MyApp"
echo ""
echo "6. Update Info.plist:"
echo " - Bundle display name: \$(DISPLAY_NAME)"
echo " - Bundle identifier: \$(PRODUCT_BUNDLE_IDENTIFIER)"
echo ""
echo "=========================================="
echo "Automated alternative:"
echo "Run: sh ios/configure-xcode-flavors.sh"
echo "=========================================="
```
---
#### Step 2.2: Create Automated Xcode Configuration Script
**Create:** `ios/configure-xcode-flavors.sh`
```bash
#!/bin/bash
# Automated Xcode flavor configuration using xcodeproj Ruby gem
# Install: gem install xcodeproj
set -e
echo "Configuring Xcode project for Flutter flavors..."
# Check if xcodeproj gem is installed
if ! gem list xcodeproj -i > /dev/null 2>&1; then
echo "Installing xcodeproj gem..."
gem install xcodeproj
fi
# Create Ruby script to modify Xcode project
cat > ios/configure_project.rb << 'RUBY_SCRIPT'
require 'xcodeproj'
project_path = 'Runner.xcodeproj'
project = Xcodeproj::Project.open(project_path)
flavors = ['dev', 'staging', 'production']
configurations = ['Debug', 'Release']
# Add build configurations
flavors.each do |flavor|
configurations.each do |config|
config_name = "#{config}-#{flavor}"
unless project.build_configurations.find { |c| c.name == config_name }
base_config = project.build_configurations.find { |c| c.name == config }
new_config = project.add_build_configuration(config_name, base_config.type)
new_config.build_settings = base_config.build_settings.dup
end
end
end
# Set flavor-specific bundle IDs
target = project.targets.first
flavors.each do |flavor|
bundle_id = flavor == 'production' ? 'com.example.app' : "com.example.app.#{flavor}"
app_name = flavor == 'production' ? 'MyApp' : "MyApp #{flavor.capitalize}"
configurations.each do |config|
config_name = "#{config}-#{flavor}"
target.build_configurations.each do |build_config|
if build_config.name == config_name
build_config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = bundle_id
build_config.build_settings['DISPLAY_NAME'] = app_name
end
end
end
end
project.save
puts "✅ Xcode project configured successfully"
RUBY_SCRIPT
cd ios
ruby configure_project.rb
cd ..
echo "✅ iOS flavor configuration complete"
echo "ℹ️ Open ios/Runner.xcworkspace to verify schemes"
```
**Make executable:**
```bash
chmod +x ios/configure-xcode-flavors.sh
```
---
#### Step 2.3: Update ios/Runner/Info.plist
**Ensure Info.plist uses build settings:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>$(DISPLAY_NAME)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<!-- ... rest of Info.plist ... -->
</dict>
</plist>
```
---
### Phase 3: Flutter Environment Configuration
#### Step 3.1: Create Environment Configuration Class
**Create:** `lib/core/config/environment.dart`
```dart
/// Environment configuration for Flutter flavors
///
/// Access environment-specific values throughout the app:
/// ```dart
/// Environment.apiBaseUrl // Current flavor's API URL
/// Environment.enableAnalytics // Current flavor's analytics setting
/// ```
class Environment {
/// Current flavor name (dev, staging, production)
static const String flavor = String.fromEnvironment(
'FLAVOR',
defaultValue: 'dev',
);
/// API base URL for current flavor
static const String apiBaseUrl = String.fromEnvironment(
'API_BASE_URL',
defaultValue: 'https://dev-api.example.com',
);
/// Whether analytics is enabled for current flavor
static const bool enableAnalytics = bool.fromEnvironment(
'ENABLE_ANALYTICS',
defaultValue: false,
);
/// Whether verbose logging is enabled for current flavor
static const bool enableLogging = bool.fromEnvironment(
'ENABLE_LOGGING',
defaultValue: true,
);
/// App name for current flavor
static const String appName = String.fromEnvironment(
'APP_NAME',
defaultValue: 'MyApp Dev',
);
// Flavor checks
static bool get isDev => flavor == 'dev';
static bool get isStaging => flavor == 'staging';
static bool get isProduction => flavor == 'production';
/// Print environment configuration (useful for debugging)
static void printConfig() {
print('=================================');
print('Environment Configuration');
print('=================================');
print('Flavor: $flavor');
print('API Base URL: $apiBaseUrl');
print('Analytics: ${enableAnalytics ? "Enabled" : "Disabled"}');
print('Logging: ${enableLogging ? "Enabled" : "Disabled"}');
print('App Name: $appName');
print('=================================');
}
}
```
---
#### Step 3.2: Create Flavor-Specific Entry Points
**Create:** `lib/main_dev.dart`
```dart
import 'package:flutter/material.dart';
import 'main_common.dart';
/// Development flavor entry point
///
/// Run: flutter run --flavor dev -t lib/main_dev.dart
void main() {
const environment = FlavorConfig(
flavor: Flavor.dev,
apiBaseUrl: 'https://dev-api.example.com',
enableAnalytics: false,
enableLogging: true,
appName: 'MyApp Dev',
);
mainCommon(environment);
}
```
**Create:** `lib/main_staging.dart`
```dart
import 'package:flutter/material.dart';
import 'main_common.dart';
/// Staging flavor entry point
///
/// Run: flutter run --flavor staging -t lib/main_staging.dart
void main() {
const environment = FlavorConfig(
flavor: Flavor.staging,
apiBaseUrl: 'https://staging-api.example.com',
enableAnalytics: true,
enableLogging: true,
appName: 'MyApp Staging',
);
mainCommon(environment);
}
```
**Create:** `lib/main_production.dart`
```dart
import 'package:flutter/material.dart';
import 'main_common.dart';
/// Production flavor entry point
///
/// Run: flutter run --flavor production -t lib/main_production.dart
void main() {
const environment = FlavorConfig(
flavor: Flavor.production,
apiBaseUrl: 'https://api.example.com',
enableAnalytics: true,
enableLogging: false,
appName: 'MyApp',
);
mainCommon(environment);
}
```
---
#### Step 3.3: Create Common Main Entry Point
**Create:** `lib/main_common.dart`
```dart
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
/// Flavor enumeration
enum Flavor {
dev,
staging,
production,
}
/// Flavor configuration
class FlavorConfig {
final Flavor flavor;
final String apiBaseUrl;
final bool enableAnalytics;
final bool enableLogging;
final String appName;
const FlavorConfig({
required this.flavor,
required this.apiBaseUrl,
required this.enableAnalytics,
required this.enableLogging,
required this.appName,
});
/// Global access to current flavor config
static FlavorConfig? _instance;
static FlavorConfig get instance {
assert(_instance != null, 'FlavorConfig not initialized');
return _instance!;
}
static void initialize(FlavorConfig config) {
_instance = config;
}
// Convenience getters
bool get isDev => flavor == Flavor.dev;
bool get isStaging => flavor == Flavor.staging;
bool get isProduction => flavor == Flavor.production;
}
/// Common main entry point for all flavors
void mainCommon(FlavorConfig config) {
// Initialize flavor config
FlavorConfig.initialize(config);
// Print config in debug mode
if (kDebugMode) {
debugPrint('=================================');
debugPrint('Flavor: ${config.flavor.name}');
debugPrint('API: ${config.apiBaseUrl}');
debugPrint('Analytics: ${config.enableAnalytics}');
debugPrint('Logging: ${config.enableLogging}');
debugPrint('=================================');
}
// Run app
runApp(MyApp(config: config));
}
/// Main app widget
class MyApp extends StatelessWidget {
final FlavorConfig config;
const MyApp({Key? key, required this.config}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
title: config.appName,
debugShowCheckedModeBanner: config.isDev || config.isStaging,
theme: ThemeData(
primarySwatch: _getThemeColor(),
useMaterial3: true,
),
home: HomePage(config: config),
);
}
/// Different theme colors for different flavors (visual debugging)
MaterialColor _getThemeColor() {
switch (config.flavor) {
case Flavor.dev:
return Colors.green; // Green for dev
case Flavor.staging:
return Colors.orange; // Orange for staging
case Flavor.production:
return Colors.blue; // Blue for production
}
}
}
/// Home page showing current flavor
class HomePage extends StatelessWidget {
final FlavorConfig config;
const HomePage({Key? key, required this.config}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(config.appName),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
_getFlavorIcon(),
size: 100,
color: Theme.of(context).primaryColor,
),
const SizedBox(height: 24),
Text(
'Flavor: ${config.flavor.name.toUpperCase()}',
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 16),
Text(
'API: ${config.apiBaseUrl}',
style: Theme.of(context).textTheme.bodyMedium,
),
const SizedBox(height: 8),
Text(
'Analytics: ${config.enableAnalytics ? "ON" : "OFF"}',
style: Theme.of(context).textTheme.bodyMedium,
),
const SizedBox(height: 8),
Text(
'Logging: ${config.enableLogging ? "ON" : "OFF"}',
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
);
}
IconData _getFlavorIcon() {
switch (config.flavor) {
case Flavor.dev:
return Icons.code;
case Flavor.staging:
return Icons.cloud_upload;
case Flavor.production:
return Icons.rocket_launch;
}
}
}
```
---
### Phase 4: Build Scripts
#### Step 4.1: Create Bash Build Scripts
**Create:** `scripts/build-dev.sh`
```bash
#!/bin/bash
# Build Development Flavor
echo "Building Dev flavor..."
# Android
echo "📱 Building Android Dev..."
flutter build apk --flavor dev -t lib/main_dev.dart --debug
# iOS
echo "🍎 Building iOS Dev..."
flutter build ios --flavor dev -t lib/main_dev.dart --debug --no-codesign
echo "✅ Dev build complete"
echo "📦 APK: build/app/outputs/flutter-apk/app-dev-debug.apk"
```
**Create:** `scripts/build-staging.sh`
```bash
#!/bin/bash
# Build Staging Flavor
echo "Building Staging flavor..."
# Android
echo "📱 Building Android Staging..."
flutter build apk --flavor staging -t lib/main_staging.dart --release
# iOS
echo "🍎 Building iOS Staging..."
flutter build ios --flavor staging -t lib/main_staging.dart --release --no-codesign
echo "✅ Staging build complete"
echo "📦 APK: build/app/outputs/flutter-apk/app-staging-release.apk"
```
**Create:** `scripts/build-production.sh`
```bash
#!/bin/bash
# Build Production Flavor
echo "Building Production flavor..."
# Android
echo "📱 Building Android Production..."
flutter build apk --flavor production -t lib/main_production.dart --release
# iOS
echo "🍎 Building iOS Production..."
flutter build ios --flavor production -t lib/main_production.dart --release --no-codesign
echo "✅ Production build complete"
echo "📦 APK: build/app/outputs/flutter-apk/app-production-release.apk"
```
**Make executable:**
```bash
chmod +x scripts/build-dev.sh
chmod +x scripts/build-staging.sh
chmod +x scripts/build-production.sh
```
---
#### Step 4.2: Create Windows Build Scripts
**Create:** `scripts/build-dev.bat`
```batch
off
REM Build Development Flavor
echo Building Dev flavor...
REM Android
echo Building Android Dev...
call flutter build apk --flavor dev -t lib/main_dev.dart --debug
REM iOS (Windows can't build iOS, show message)
echo iOS build requires macOS
echo Dev build complete
echo APK: build\app\outputs\flutter-apk\app-dev-debug.apk
```
**Create:** `scripts/build-staging.bat`
```batch
off
REM Build Staging Flavor
echo Building Staging flavor...
REM Android
echo Building Android Staging...
call flutter build apk --flavor staging -t lib/main_staging.dart --release
REM iOS (Windows can't build iOS, show message)
echo iOS build requires macOS
echo Staging build complete
echo APK: build\app\outputs\flutter-apk\app-staging-release.apk
```
**Create:** `scripts/build-production.bat`
```batch
off
REM Build Production Flavor
echo Building Production flavor...
REM Android
echo Building Android Production...
call flutter build apk --flavor production -t lib/main_production.dart --release
REM iOS (Windows can't build iOS, show message)
echo iOS build requires macOS
echo Production build complete
echo APK: build\app\outputs\flutter-apk\app-production-release.apk
```
---
### Phase 5: VS Code Launch Configuration
**Create:** `.vscode/launch.json`
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Dev Flavor",
"request": "launch",
"type": "dart",
"program": "lib/main_dev.dart",
"args": [
"--flavor",
"dev"
]
},
{
"name": "Staging Flavor",
"request": "launch",
"type": "dart",
"program": "lib/main_staging.dart",
"args": [
"--flavor",
"staging"
]
},
{
"name": "Production Flavor",
"request": "launch",
"type": "dart",
"program": "lib/main_production.dart",
"args": [
"--flavor",
"production"
]
}
]
}
```
---
## Summary & Output
**Return Results:**
```json
{
"status": "success",
"ios_schemes_created": {{environments.length}},
"android_flavors_created": {{environments.length}},
"entry_points_generated": [
{{#each environments}}
"lib/main_{{this}}.dart"{{#unless }},{{/unless}}
{{/each}}
],
"build_scripts_created": [
{{#each environments}}
"scripts/build-{{this}}.sh",
"scripts/build-{{this}}.bat"{{#unless }},{{/unless}}
{{/each}}
],
"environment_config_path": "lib/core/config/environment.dart",
"configuration_files": [
"android/app/build.gradle (updated)",
"ios/Runner/Info.plist (updated)",
"lib/main_common.dart (created)",
".vscode/launch.json (created)"
],
"next_steps": [
"Run iOS configuration: sh ios/configure-xcode-flavors.sh",
"Test dev flavor: flutter run --flavor dev -t lib/main_dev.dart",
"Test staging flavor: flutter run --flavor staging -t lib/main_staging.dart",
"Test production flavor: flutter run --flavor production -t lib/main_production.dart",
"Build release: sh scripts/build-production.sh"
]
}
```
---
## Success Criteria
Flavor setup succeeds if:
- ✅ Android build.gradle has productFlavors configuration
- ✅ iOS Info.plist uses $(DISPLAY_NAME) and $(PRODUCT_BUNDLE_IDENTIFIER)
- ✅ All entry point files created (main_*.dart)
- ✅ Common main created with FlavorConfig
- ✅ Build scripts created for all flavors
- ✅ VS Code launch configurations created
- ✅ No Flutter errors (`flutter analyze` passes)
---
## Usage Examples
### Run specific flavor:
```bash
# Development
flutter run --flavor dev -t lib/main_dev.dart
# Staging
flutter run --flavor staging -t lib/main_staging.dart
# Production
flutter run --flavor production -t lib/main_production.dart
```
### Build specific flavor:
```bash
# Using build scripts
sh scripts/build-dev.sh
sh scripts/build-staging.sh
sh scripts/build-production.sh
# Or manually
flutter build apk --flavor production -t lib/main_production.dart --release
```
### Access flavor config in code:
```dart
import 'package:myapp/main_common.dart';
// Get current flavor
final flavor = FlavorConfig.instance.flavor;
// Check environment
if (FlavorConfig.instance.isDev) {
print('Running in development');
}
// Use environment-specific API
final apiUrl = FlavorConfig.instance.apiBaseUrl;
```
---
## Time Estimate
| Phase | Time |
|-------|------|
| Android configuration | 30s |
| iOS configuration | 45s |
| Flutter entry points | 30s |
| Build scripts | 20s |
| VS Code config | 10s |
| **Total** | **~2-3 minutes** |
**Compare to manual:** 2-3 hours → **40-60x faster!**