Skip to content
Back to archipelago.banuacoder.com

Shared Packages

How to manage Flutter environment variables per flavor ​

Free Reference for shared_app_config: every variable, option and package it generates. Command: archipelago generate shared_app_config

Generate the shared config package with envied, keep variables per flavor, read them through AppEnv, and add a new variable.

What you'll learn ​

  • Generating the shared config package with envied
  • Keeping environment variables per flavor
  • Reading values through the public AppEnv wrapper
  • Adding a variable and switching flavors

Prerequisites ​

New projects already include this brick. The monorepo generator also writes the .env.development, .env.staging and .env.production files with placeholder values.

Step 1: Generate the Shared App Config ​

bash
archipelago generate shared_app_config

The prompts are:

  • appName: your app name, for example MyApp
  • analyticsVendors: the analytics vendors you use. appsflyer, mixpanel and moengage add key getters. firebase adds nothing.
  • featureFlagVendor: flagr adds a base URL getter. The other values add nothing.
  • isForMonorepo: leave this as true

Or use a config file:

json
{
  "appName": "MyApp",
  "analyticsVendors": [],
  "featureFlagVendor": "none",
  "isForMonorepo": true
}
bash
archipelago generate shared_app_config --config config.json

Vendor bricks read AppEnv.<key> directly. They fail to compile with undefined_getter if you did not select their vendor here.

Step 2: Understand the Generated Structure ​

text
shared/app_config/
├── .env.example              # Placeholder template, committed
├── .gitignore                # Ignores .env and env.g.dart
├── build.yaml
├── lib/
│   ├── app_config.dart       # Barrel: AppEnv and Flavor
│   └── src/
│       ├── env/
│       │   ├── env.dart      # Internal @Envied class
│       │   └── app_env.dart  # Public AppEnv wrapper
│       └── flavor.dart       # FlavorStatus and Flavor
└── pubspec.yaml

env.g.dart is generated by build_runner. It holds the obfuscated values and is not committed.

Step 3: Set the Variables per Flavor ​

The values live in .env.<flavor> files next to .env.example. monorepo_toolkit env init creates them from the example if they are missing.

bash
# .env.development
API_BASE_URL=https://api-dev.myapp.com
APP_NAME=MyApp Dev
AES_KEY=replace-with-a-dev-key
DATABASE_URL=replace-me

Use other values in .env.production. Do not commit real secrets. Fill the production file from your CI secret store.

Step 4: Switch Flavors and Generate ​

env switch copies the matching file to .env. Then build_runner reads only that flavor:

bash
dart run monorepo_toolkit env switch --flavor development
dart run build_runner build --delete-conflicting-outputs

Step 5: Read Values in Code ​

Application code uses AppEnv. It never touches the internal Env class:

dart
import 'package:app_config/app_config.dart';

final baseUrl = AppEnv.apiBaseUrl;
final appName = AppEnv.appName;

Vendor getters such as AppEnv.appsflyerDevKey, AppEnv.mixpanelToken, AppEnv.moengageAppId and AppEnv.flagrBaseUrl exist only when you selected that vendor.

Step 6: Add a Variable ​

Run the helper:

bash
dart run monorepo_toolkit env add MY_VAR

Or do it by hand:

  1. Add an @EnviedField() to env.dart and a getter to app_env.dart.
  2. Add the key to .env.example and every .env.<flavor> file.
  3. Run env switch for your current flavor.
  4. Run build_runner.

Step 7: Use the Flavor ​

Set the flavor once in main() before first use:

dart
Flavor.status = FlavorStatus.development;

if (Flavor.isProduction) {
  // production-only behavior
}

Flavor.current throws a StateError if the status is not set.

Why Envied Over dart-define ​

ApproachDownside
--dart-defineValues show in the process list and are not obfuscated
enviedValues are compiled in and obfuscated

Envied generates obfuscated Dart code, so secrets are not plain strings in the binary. Obfuscation slows extraction. It does not make a secret safe. Never ship a server secret in an app.

Common Customizations ​

CustomizationWhere to Change
Add env vars.env.* files, env.dart and app_env.dart
Change flavorsflavor.dart and monorepo_toolkit flavor
CI secretsWrite the .env.<flavor> file from the CI secret store

Next Steps ​