How I Made My Flutter App Modular with Multiple Flavors
FlutterAndroidBuild SystemDevelopment

How I Made My Flutter App Modular with Multiple Flavors

6 min read

How I Made My Flutter App Modular with Multiple Flavors

In this post, I'll share how I structured a modular Flutter app with multiple build flavors—one of which required unique Android permissions and behavior. Managing configurations across environments while avoiding code duplication was a fun challenge.

Why Flavors?

We needed to support:

  • A consumer-facing app (no advanced permissions)
  • An internal tester/debug app (with elevated permissions)

Rather than clone the app or manually swap configs, flavors gave us clean separation and automation.

Flavor Setup

  1. Defined flavors in build.gradle:
Copy
productFlavors { consumer { dimension "app" applicationIdSuffix ".consumer" } internal { dimension "app" applicationIdSuffix ".internal" } }
  1. Used different AndroidManifest.xml files:
src/
├── consumer/
│   └── AndroidManifest.xml
├── internal/
│   └── AndroidManifest.xml
  1. Flutter flavor entry points:
Copy
flutter run --flavor consumer -t lib/main_consumer.dart flutter run --flavor internal -t lib/main_internal.dart

Challenges

  • Ensuring all shared code was kept outside flavor-specific files
  • Avoiding duplication across manifests and Gradle configs

Tips

  • Use conditional imports for flavor-specific logic
  • Externalize secrets per flavor
  • Automate build matrix via CI

Outcome

  • Clean, maintainable codebase
  • Fast switching between environments
  • Fewer config bugs in production