A Complete Guide to Implementing Flutter Flavors and Why They're Important


Flutter Flavors Explained: How to Implement and Why You Should
So, you’ve built your Flutter app, and everything is looking great. But then you realize:
You need a development version to test features.
A staging version for your QA team.
And a production version for real users.
How do you manage all these versions without going crazy?
That’s where Flavours in Flutter come in. Let’s break it down.
🌿 What are Flavours, Anyway?
Think of Flavours like different “toppings” on your app.
Same base app, but slightly different depending on what you need.
For example:
The dev app might use a test API, say “Dev Mode” in the title, and have a different icon.
The prod app connects to the real API and shows the proper logo.
The staging app is what your testers see.
With Flavours, you can:
✅ Have different configurations (API endpoints, app names, icons)
✅ Build specific versions of your app without manual tweaks
✅ Avoid the nightmare of deploying test builds to real users!
🎯 Why Bother with Flavours?
Good question!
Imagine you’re working on a new feature, but you don’t want to break the live app. Or you want your testers to check something before releasing it.
Flavours let you:
Build safe environments for testing
Separate production from development
Ship custom versions for different clients
And you don’t have to keep swapping files or commenting code in and out.
🛠️ How to Set Up Flavours (Step by Step)
Let’s get to the fun part—setting up Flavours in your Flutter project.
1️⃣ Create Entry Points for Each Flavour
Start by creating separate Dart files for each flavour:
// lib/main_dev.dart
import 'package:your_app/main.dart' as app;
void main() {
const flavour = "Development";
app.main(flavour);
}
// lib/main_prod.dart
import 'package:your_app/main.dart' as app;
void main() {
const flavour = "Production";
app.main(flavour);
}
Then update your main.dart
:
// lib/main.dart
import 'package:flutter/material.dart';
void main([String flavour = "Production"]) {
runApp(MyApp(flavour: flavour));
}
class MyApp extends StatelessWidget {
final String flavour;
const MyApp({super.key, required this.flavour});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp ($flavour)',
home: Scaffold(
appBar: AppBar(title: Text('Hello from $flavour')),
body: Center(child: Text('Running on $flavour')),
),
);
}
}
Now, when you run lib/main_dev.dart
, it shows "Development"!
2️⃣ Set Up Android Flavours
In your android/app/build.gradle
file:
android {
...
flavorDimensions "app"
productFlavors {
dev {
dimension "app"
applicationIdSuffix ".dev"
versionNameSuffix "-dev"
}
prod {
dimension "app"
}
}
}
This lets Android know there are different "flavours" of your app.
3️⃣ Set Up iOS Flavours
iOS is a bit more manual:
In Xcode, duplicate the schemes:
Runner
→Runner-dev
Runner
→Runner-prod
Change the Bundle Identifier in each scheme:
com.yourcompany.app.dev
com.yourcompany.app
This keeps the apps separate when installed.
4️⃣ Run Your Flavours
Use Flutter’s -t
flag:
flutter run -t lib/main_dev.dart
flutter run -t lib/main_prod.dart
Or build them:
flutter build apk -t lib/main_dev.dart
flutter build ipa -t lib/main_prod.dart
5️⃣ Handle Different Configurations
Need different API URLs or secrets?
Use a config.dart
file or the flutter_dotenv package.
For example:
class Config {
static const apiUrl = String.fromEnvironment('API_URL', defaultValue: 'https://api.prod.com');
}
Or, with dotenv
, load .env
files per flavour.
🌟 Best Practices (From Experience)
✅ Name your apps clearly: "MyApp Dev", "MyApp Staging".
✅ Use different icons for each flavour to avoid mix-ups.
✅ Automate builds with CI/CD.
✅ Never hardcode secrets in your code—use environment variables.
✨ Final Thoughts
Flavours in Flutter save you time, stress, and mistakes.
Once set up, you can easily switch between environments, test safely, and deploy with confidence.
Want a hands-on guide or GitHub example? Let me know, and I’ll help you get started!
Happy coding! 🚀
Subscribe to my newsletter
Read articles from Gidudu Nicholas directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Gidudu Nicholas
Gidudu Nicholas
Hello, I am a senior Flutter developer with vast experience in crafting mobile applications. I am a seasoned community organizer with vast experience in launching and building Google Developer communities under GDG Bugiri Uganda and Flutter Kampala.