Skip to content
Back to archipelago.banuacoder.com

Shared Packages

shared_app_config Free ​

Tier
Freeversion 1.2.6
Command
archipelago generate shared_app_config
Generates
  • shared/app_config

Centralized configuration package for environment variables and flavor management, using envied for obfuscated compile-time env var injection, plus vendor-gated AppEnv getters for analytics and feature-flag vendors that need an API key.

What it is ​

Every generated app needs one place to read the active flavor's secrets (API base URL, AES key, database URL) and, if an analytics or feature-flag vendor needs its own key, that key too. shared_app_config is that package — generated once, early, as part of flutter_modular_monorepo scaffolding. Every other package that needs a secret or the current flavor depends on it.

Variables ​

VariableTypeDefaultDescription
appNamestringMyAppThe name of your application
analyticsVendorsarray (firebase, appsflyer, mixpanel, moengage, none)[]Analytics vendors to wire through AppEnv/.env. Only vendors whose SDK needs an API key at init time get a getter + .env.example placeholder: appsflyer → appsflyerDevKey/appsflyerAppId, mixpanel → mixpanelToken, moengage → moengageAppId. firebase reads config from google-services.json/GoogleService-Info.plist instead and gets nothing added.
featureFlagVendorenum (flagr, remote_config, custom, none)noneFeature flag vendor. Only flagr gets an AppEnv.flagrBaseUrl getter + .env.example placeholder — remote_config reads config from the same Firebase project as firebase analytics, so it needs nothing here.
isForMonorepobooleantrueWhether this is being generated as part of a monorepo

pre_gen.dart derives useAppsFlyerAnalytics, useMixpanelAnalytics, useMoEngageAnalytics, useFlagr booleans from the two variables above — these Mustache-conditional flags are not declared in brick.yaml (per project convention; declaring derived flags there makes mason make -c prompt and hang CI).

Usage ​

Interactive ​

bash
archipelago generate shared_app_config

Non-interactive (CI) ​

bash
archipelago generate shared_app_config --config my_config.json

Generated Structure ​

text
shared/
└── app_config/
    ├── .env.example              # Template placeholders (committed)
    ├── .gitignore                # Ignores .env and env.g.dart
    ├── analysis_options.yaml
    ├── build.yaml
    ├── lib/
    │   ├── app_config.dart       # Barrel: exports app_env.dart + flavor.dart
    │   └── src/
    │       ├── env/
    │       │   ├── env.dart      # @Envied(path: '.env') — internal, not exported
    │       │   └── app_env.dart  # Public AppEnv wrapper delegating to Env
    │       └── flavor.dart       # FlavorStatus enum + Flavor holder
    └── pubspec.yaml

Only .env.example ships with the brick — .env.development/.env.staging/.env.production are not part of __brick__/. They're created afterward by monorepo_toolkit's env init command (from env_sync), which scaffolds per-flavor .env.<flavor> files sourced from .env.example. env.g.dart (the obfuscated envied output) is generated by build_runner, not shipped as a template.

How env works ​

A single Env class (internal — not part of the app_config.dart barrel) reads from the .env file at the package root:

dart
@Envied(path: '.env', obfuscate: true, useConstantCase: true)
abstract final class Env {
  @EnviedField()
  static final String apiBaseUrl = _Env.apiBaseUrl;
  // ... aesKey, databaseUrl, and vendor-gated fields
}

monorepo_toolkit env switch <flavor> copies the matching .env.<flavor> source file to .env; build_runner then reads only that flavor's secrets into env.g.dart. Application code never touches Env directly — it goes through the public wrapper:

dart
final baseUrl = AppEnv.apiBaseUrl;
final appName = AppEnv.appName;
// Only present when the matching vendor was selected at generation time:
// AppEnv.appsflyerDevKey / AppEnv.appsflyerAppId / AppEnv.mixpanelToken /
// AppEnv.moengageAppId / AppEnv.flagrBaseUrl

Flavor ​

dart
Flavor.status = FlavorStatus.development; // set once in main(), before first use
Flavor.current;      // throws StateError if not yet set
Flavor.isDevelopment / Flavor.isStaging / Flavor.isProduction;

FlavorStatus.code returns the short file-suffix code (dev/sta/pro) used for .env.<code> naming conventions.

Build-time env swap ​

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

See the Environment Sync guide for the full env switch/env init reference and CI integration.

Adding environment variables ​

  1. Add @EnviedField() to env.dart (or run dart run monorepo_toolkit env add MY_VAR).
  2. Add the key to .env.example and all .env.<flavor> files.
  3. Run dart run monorepo_toolkit env switch <current_flavor>.
  4. Run dart run build_runner build --delete-conflicting-outputs.

Wiring ​

hooks/post_gen.dart registers the package into the melos workspace (WorkspaceHelper.addToWorkspace(rootPath, 'shared/app_config')) when isForMonorepo is true; standalone generation skips this.

Dependencies ​

envied (runtime), envied_generator + build_runner (dev). No dependency on other Archipelago bricks — but analytics-vendor and feature-flag-vendor bricks (appsflyer_analytics_impl, mixpanel_analytics_impl, moengage_analytics_impl, flagr_feature_flag_impl) read AppEnv.<key> directly and will fail to compile with an undefined_getter error if the matching analyticsVendors/featureFlagVendor selection wasn't made when this brick was generated (fixed in 1.1.0 for the analytics vendors and 1.2.0 for flagr).

Limitations ​

No native/platform setup — pure Dart package. .env.<flavor> scaffolding is a separate manual step (monorepo_toolkit env init), not automatic on archipelago generate.

Changelog ​

Run archipelago brick info shared_app_config to see the latest published version. Enterprise customers can read the full CHANGELOG.md in the brick source repository.