Firebase Flavors
A Dart CLI tool for configuring Firebase within your project for multiple Flutter flavors.
Features
- 🚀 Automatic Configuration Detection: Automatically detects flavors, bundle IDs, and app names from your Android Gradle files or iOS project files
- 📱 Multi-Platform Support: Configure Firebase for both Android and iOS platforms
- 🎯 Flavor Management: Easily manage multiple Firebase projects for different app flavors
- ⚙️ Flexible Configuration: Customize package names, bundle IDs, and output paths per flavor
- 🔧 Xcode Integration: Automatically sets up Xcode run scripts for iOS Google Services configuration
- 📝 YAML Configuration: Simple, human-readable YAML configuration file
Installation
Using pub (Recommended)
dart pub global activate firebase_flavors
You can then run it from anywhere with:
dart run firebase_flavors [command]
Make sure your PATH includes the pub cache bin directory:
- macOS/Linux:
~/.pub-cache/bin - Windows:
%APPDATA%\Pub\Cache\bin
Development Install (in your project)
Add this to your project's pubspec.yaml under dev_dependencies:
dart pub add dev:firebase_flavors
You can then run it from your project root with:
dart run firebase_flavors:firebase_flavors [command]
Prerequisites
Before using firebase_flavors, ensure you have the following installed:
-
FlutterFire CLI: Required for Firebase configuration
dart pub global activate flutterfire_cli -
Ruby (for iOS configuration): Required for Xcode project manipulation
- macOS: Usually pre-installed
- Linux/Windows: Install Ruby
-
xcodeproj gem (for iOS configuration): Required for modifying Xcode projects
gem install xcodeproj -
Flutter: Your Flutter project should be set up with flavors configured in your
build.gradle(Android) or Xcode schemes (iOS)
Quick Start
1. Initialize Configuration
Run the init command in your Flutter project root:
firebase_flavors init
This command will:
- Detect your app's flavors from Android Gradle files or iOS project files
- Detect your base bundle ID and app name
- Generate a
firebase_flavors.yamlconfiguration file
2. Edit Configuration
Open firebase_flavors.yaml and update the Firebase project IDs for each flavor:
flavors:
dev:
firebaseProjectId: your-dev-project-id
# ... other settings
staging:
firebaseProjectId: your-staging-project-id
# ... other settings
prod:
firebaseProjectId: your-prod-project-id
# ... other settings
3. Configure Firebase
Run the configure command to set up Firebase for your flavors:
firebase_flavors configure
This will configure all flavors, or specify specific ones:
firebase_flavors configure dev,staging
Commands
init
Initializes a new firebase_flavors.yaml configuration file.
firebase_flavors init [--force] [--config <path>]
Options:
--force: Overwrite existing configuration file--config <path>: Specify custom config file path (default:firebase_flavors.yaml)
What it does:
- Detects flavors from
android/app/build.gradleor iOS project files - Detects base bundle ID from Android or iOS configuration
- Detects app name from project files
- Generates a YAML configuration file with detected values
configure
Configures Firebase for specified flavors.
firebase_flavors configure [flavor1,flavor2,...] [--skip-firebase] [--skip-xcode] [--config <path>]
Arguments:
flavor1,flavor2,...: Comma-separated list of flavors to configure (optional, defaults to all flavors)
Options:
--skip-firebase: Skip Firebase configuration (only set up Xcode scripts)--skip-xcode: Skip Xcode run script setup (only configure Firebase)--config <path>: Specify custom config file path (default:firebase_flavors.yaml)
What it does:
- Runs
flutterfire configurefor each flavor - Downloads and places
google-services.jsonfiles for Android - Downloads and places
GoogleService-Info.plistfiles for iOS - Sets up Xcode run scripts to copy the correct iOS config file based on build configuration
- Generates Dart options files (
firebase_options_*.dart) for each flavor
list
Lists all configured flavors and their details.
firebase_flavors list [--config <path>]
Options:
--config <path>: Specify custom config file path (default:firebase_flavors.yaml)
What it shows:
- App name and base bundle ID
- Platform paths (Android source base, iOS Xcode project, etc.)
- For each flavor:
- Firebase project ID
- Supported platforms
- Android package name and config file path
- iOS bundle ID and config file path
- Dart options output path
Global Options
All commands support these global options:
--help, -h: Show help information--verbose, -v: Show additional debug output--version: Show tool version--config <path>, -c: Specify custom config file path (default:firebase_flavors.yaml)
Configuration File Structure
The firebase_flavors.yaml file has the following structure:
# App-level configuration (required)
appName: MyApp
baseBundleId: com.example.app
# Android configuration (optional - all fields have defaults)
android:
srcBase: android/app/src # Optional, default: android/app/src
# iOS configuration (optional - all fields have defaults)
ios:
xcodeprojPath: ios/Runner.xcodeproj # Optional, default: ios/Runner.xcodeproj
target: Runner # Optional, default: Runner
configBase: ios/Runner/Runner # Optional, default: ios/Runner/Runner
# Flavor-specific configuration
flavors:
dev:
firebaseProjectId: my-dev-project-id # Required
androidPackageSuffix: .dev # Optional, default: null (no suffix)
dartOptionsOut: lib/firebase_options_dev.dart # Optional, default: lib/firebase_options_{flavor}.dart
androidSrcDir: dev # Optional, default: {flavor}
iosConfigDir: dev # Optional, default: {flavor}
platforms: android,ios # Optional, default: null (all platforms)
iosBundleId: com.example.app.dev # Optional, default: null (uses baseBundleId)
prod:
firebaseProjectId: my-prod-project-id # Required
androidPackageSuffix: "" # Optional, empty string = no suffix (default: null)
# All other fields are optional with defaults as shown above
Configuration Fields
Global Configuration
appName(required): Your app's display namebaseBundleId(required): Base bundle/package identifier (e.g.,com.example.app)
Android Configuration (all optional)
android.srcBase(optional): Base directory for Android source files. Default:android/app/src
iOS Configuration (all optional)
ios.xcodeprojPath(optional): Path to your Xcode project file. Default:ios/Runner.xcodeprojios.target(optional): Xcode target name. Default:Runnerios.configBase(optional): Base directory for iOS configuration files. Default:ios/Runner/Runner
Flavor Configuration
firebaseProjectId(required): Your Firebase project ID for this flavorandroidPackageSuffix(optional): Suffix to append to base bundle ID for Android (e.g.,.dev,.staging). Default:null(no suffix). If provided without a leading dot, one will be added automaticallydartOptionsOut(optional): Path where the Dart options file will be generated. Default:lib/firebase_options_{flavor}.dartandroidSrcDir(optional): Directory name underandroid/srcBasewheregoogle-services.jsonwill be placed. Default:{flavor}(the flavor name)iosConfigDir(optional): Directory name underios.configBasewhereGoogleService-Info.plistwill be placed. Default:{flavor}(the flavor name)platforms(optional): Comma-separated list of platforms (android,ios). If omitted or empty, all platforms are configured. Default:null(all platforms)iosBundleId(optional): Override iOS bundle ID for this flavor. If omitted or empty, usesbaseBundleId. Default:null(usesbaseBundleId)
Examples
Example 1: Basic Setup
# 1. Initialize
firebase_flavors init
# 2. Edit firebase_flavors.yaml with your Firebase project IDs
# 3. Configure all flavors
firebase_flavors configure
Example 2: Configure Specific Flavors
# Configure only dev and staging
firebase_flavors configure dev,staging
Example 3: Skip Xcode Setup
# Configure Firebase but skip Xcode run script setup
firebase_flavors configure --skip-xcode
Example 4: Custom Config File
# Use a custom configuration file
firebase_flavors init --config custom_config.yaml
firebase_flavors configure --config custom_config.yaml
Example 5: Verbose Output
# Get detailed debug information
firebase_flavors configure --verbose
Project Structure
After configuration, your project structure will look like this:
your_flutter_project/
├── firebase_flavors.yaml
├── lib/
│ ├── firebase_options_dev.dart
│ ├── firebase_options_staging.dart
│ └── firebase_options_prod.dart
├── android/
│ └── app/
│ └── src/
│ ├── dev/
│ │ └── google-services.json
│ ├── staging/
│ │ └── google-services.json
│ └── prod/
│ └── google-services.json
└── ios/
└── Runner/
└── Runner/
├── dev/
│ └── GoogleService-Info.plist
├── staging/
│ └── GoogleService-Info.plist
└── prod/
└── GoogleService-Info.plist
Using in Your Flutter App
After configuration, use separate Dart entrypoints for each flavor, as recommended by Firebase. This allows you to specify which firebase_options_x.dart file to include per flavor, without needing conditional imports or extra build tools.
For example, create separate files in your lib/ directory:
lib/main_dev.dart
import 'package:flutter/widgets.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options_dev.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
lib/main_staging.dart
import 'package:flutter/widgets.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options_staging.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
lib/main_prod.dart
import 'package:flutter/widgets.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options_prod.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
To run a specific flavor, provide the corresponding entrypoint with Flutter's -t (target) flag:
# Development flavor
flutter run -t lib/main_dev.dart
# Staging flavor
flutter run -t lib/main_staging.dart
# Production flavor
flutter run -t lib/main_prod.dart
Tip: This is the recommended approach for multi-flavor support. Each entrypoint statically imports the correct
firebase_options_*.dartfile for its flavor, avoiding runtime ambiguity and making builds more robust and predictable.
Troubleshooting
flutterfire CLI not found
Error: flutterfire CLI is not installed or not found on your PATH
Solution:
dart pub global activate flutterfire_cli
# Make sure ~/.pub-cache/bin is in your PATH
xcodeproj gem not found
Error: xcodeproj gem is not installed
Solution:
gem install xcodeproj
Configuration file not detected
Error: No project configuration detected, using defaults
Solution: The tool will use default values. You can manually edit firebase_flavors.yaml after initialization to match your project structure.
Firebase project ID not set
Error: firebaseProjectId is required
Solution: Make sure each flavor in firebase_flavors.yaml has a valid firebaseProjectId set.
Xcode script setup fails
Error: Issues with Xcode run script setup
Solution:
- Ensure Ruby and xcodeproj gem are installed
- Check that your Xcode project path is correct in the configuration
- Try running with
--skip-xcodeto skip this step and set up manually
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is open source. Please check the repository for license information.
Support
For issues, questions, or contributions, please visit the GitHub repository.