Skip to content

Environment Sync

The env command manages environment variables across flavors in the shared/app_config package. It integrates with envied for type-safe, code-generated environment access.

Subcommands

env init

Initializes the environment configuration structure in shared/app_config:

bash
dart run monorepo_toolkit env init

# Specify initial variables (defaults to API_BASE_URL and AES_KEY)
dart run monorepo_toolkit env init --var API_BASE_URL --var AES_KEY --var SECRET

This creates:

  • Per-flavor envied classes (e.g., DevelopmentEnv, StagingEnv, ProductionEnv)
  • .env template files per flavor (.env.development, .env.staging, .env.production)
  • The main Env class that delegates to the active flavor's envied class
  • Updates to the FlavorStatus enum

env add

Adds a new environment variable to all flavor .env files and envied classes:

bash
dart run monorepo_toolkit env add API_SECRET

Variable names must start with an uppercase letter and contain only uppercase letters, numbers, and underscores (e.g., API_KEY, DATABASE_URL, SECRET_123).

This:

  1. Appends the variable to each flavor's .env file
  2. Adds the corresponding @EnviedField annotation to each flavor's envied class
  3. Updates the main Env class

You then fill in the actual values per flavor:

bash
# .env.development
API_SECRET=dev_secret_key

# .env.staging
API_SECRET=staging_secret_key

# .env.production
API_SECRET=production_secret_key

env sync

Synchronizes the FlavorStatus enum and envied classes with the flavors defined in flavors.yaml:

bash
dart run monorepo_toolkit env sync

This regenerates the FlavorStatus enum, per-flavor envied classes, and the main Env class to match the current flavor list. Run this after adding or removing a flavor in flavors.yaml.

Integration with envied

The app_config package uses envied to generate type-safe access to environment variables. After running env add and filling in values, run code generation:

bash
melos run build:app_config
# or
dart run build_runner build --delete-conflicting-outputs

This generates a class with compile-time environment access:

dart
@Envied(path: '.env.development')
abstract class DevelopmentEnv {
  @EnviedField(varName: 'API_BASE_URL')
  static const String apiBaseUrl = _DevelopmentEnv.apiBaseUrl;
}

Flavor-specific .env files

Each flavor has its own .env file:

shared/app_config/
  .env.development
  .env.staging
  .env.production

The active flavor is set at app startup via Flavor.status in bootstrap.dart, which determines which envied class is used at compile time.

Workflow

  1. Define flavors in flavors.yaml at the workspace root
  2. Run dart run monorepo_toolkit env init to create .env files and envied classes
  3. Run dart run monorepo_toolkit env add <VAR_NAME> for each new variable
  4. Fill in values per flavor in the .env.* files
  5. Run dart run monorepo_toolkit env sync after changing flavors in flavors.yaml
  6. Run code generation to produce the envied classes

Melos shortcuts

bash
melos run env:init       # Initialize env config
melos run env:add        # Add env variable (pass var name after --)
melos run env:sync       # Sync flavor enum and envied classes
melos run env:generate   # Generate envied code

Built by Banua Coder