Black Friday Sale

Flutter Foundations Course

Buy now and get 33% off the regular price!

View Course

Flutter Flavors Setup with multiple Firebase Environments using FlutterFire and Very Good CLI

When planning for a Flutter app release, it's important to setup different development environments:

  • development: used by developers while building the app
  • staging: used to distribute builds to the Q/A team and other product stakeholders/clients
  • production: used by all the users that download the live app from the App Store

Setting things up this way makes everyone's life easier, and ensures that data in the production environmnent is not altered by mistake during development. 👍


As far as Flutter goes, we can use flavors to setup different environments.

But if our Flutter app uses a Firebase backend, things get a bit more involved and setting things correctly used to require a lot of manual configuration steps.

Luckily, things got a lot easier with the introduction of tools such as Very Good CLI and FlutterFire CLI.

And that's what this article is about: how to setup up a Flutter & Firebase app with multiple flavors and environments, in a few simple steps.

What are Flutter Flavors?

Flavors let you define different build configurations and change them as needed. For example, you may want to call different API endpoints, use different API keys, or even have different app icons for each configuration.

Flavors are easy to use when building your Flutter app from the command line:

flutter build --flavor development

On Android, this determines which product flavor is used during the Gradle build process.

On iOS, things can be configured so that a different Xcode scheme is used for each flavor.

And as of December 2021, the whole process can be (mostly) automated. Let's see how.

Flutter & Firebase Apps with Multiple Flavors using Very Good CLI

Very Good Ventures released Very Good CLI, a tool that we can use to create Flutter apps pre-configured with build flavors as well as many other useful features.

All we have to do is to install it:

dart pub global activate very_good_cli

Then we can use it to create a new Flutter app like so:

very_good create --org-name com.codewithandrea my_test_app_flavors

If we look at the generated Flutter app, we'll find the following files inside lib:

lib/ main_development.dart main_production.dart main_staging.dart

And we can run the generated app by passing the correct arguments on the command line:

# Run development flutter run --flavor development --target lib/main_development.dart # Run staging flutter run --flavor staging --target lib/main_staging.dart # Run production flutter run --flavor production --target lib/main_production.dart

Alternatively, we can choose the flavor directly from VSCode, as Very Good CLI has already generated multiple launch configurations for us:

VS Code launch flavors
VS Code launch flavors

But the best part is that the Xcode and Android projects are already configured to run with multiple flavors, meaning that we don't have to mess about with Xcode schemes or gradle files. 💯

Setting up multiple Firebase environments

Very Good CLI helps us with the Flutter side of things.

But what about Firebase?

Well, we can use the FlutterFire CLI tool to generate correct Firebase configuration for our project, as I have explained in my previous article:

But this time, we have to create one Firebase project for each Flutter flavor. For consistency, we could name the Firebase projects like so:

  • my-test-app-flavors-dev
  • my-test-app-flavors-stg
  • my-test-app-flavors-prod

And then, we can use the FlutterFire CLI generate the correct Dart initialization file for each Flutter flavor, with this command:

# Dev environment (note: do the same for Stg and Prod) flutterfire config \ --project=my-test-app-flavors-dev \ --out=lib/firebase_options_dev.dart \ --ios-bundle-id=com.codewithandrea.my-test-app-flavors.dev \ --macos-bundle-id=com.codewithandrea.my-test-app-flavors.dev \ --android-app-id=com.codewithandrea.my_test_app_flavors.dev

When we do this, we have to use the correct bundle ID on iOS and macOS. This can be found by opening the project build settings in Xcode:

Xcode project settings for multiple flavors
Xcode project settings for multiple flavors

And on Android, the correct applicationId can be found inside android/app/build.gradle, along with the applicationIdSuffix used for each flavor:

android { ... defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.codewithandrea.my_test_app_flavors" minSdkVersion 16 targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } ... flavorDimensions "default" productFlavors { production { dimension "default" applicationIdSuffix "" manifestPlaceholders = [appName: "My Test App Flavors"] } staging { dimension "default" applicationIdSuffix ".stg" manifestPlaceholders = [appName: "[STG] My Test App Flavors"] } development { dimension "default" applicationIdSuffix ".dev" manifestPlaceholders = [appName: "[DEV] My Test App Flavors"] } } ... }

Dart initialization for each Flutter flavor

Once we have run flutterfire config for each Flutter flavor, the last step is to use the correct Firebase options for each target:

// main_development.dart import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:my_test_app_flavors/app/view/app.dart'; import 'package:my_test_app_flavors/firebase_options_dev.dart'; Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); runApp(const App()); }

And once this is done, we can choose a flavor and run the app on iOS, Android, or web:

VS Code launch flavors
VS Code launch flavors

Sweet, isn't it? 😀

Note about using Firebase Analytics & Crashlytics

Certain Firebase services still require some platform-specific configuration to work correctly.

In particular, see this comment from this open issue in the Flutterfire client.

Conclusion

As we have seen, we can use the new FlutterFire CLI to configure our Firebase project with just one command.

And if we want to add flavors to the mix, Very Good CLI makes our life easier.

While the entire process can't be completely automated (yet), using FlutterFire and Very Good CLI together can save us a ton of time (and mistakes)! 🚀

Happy coding!

References

Want More?

Invest in yourself with my high-quality Flutter courses.

The Complete Dart Developer Guide

The Complete Dart Developer Guide

Learn Dart Programming in depth. Includes: basic to advanced topics, exercises, and projects. Fully updated to Dart 2.15.

The Complete Flutter Course Bundle

The Complete Flutter Course Bundle

Learn about State Management, App Architecture, Navigation, Testing, and much more by building a full-stack Flutter eCommerce app on iOS, Android, and web.

Flutter Animations Masterclass - Full Course

Flutter Animations Masterclass - Full Course

Master Flutter animations and build a completely custom habit tracking application.