Shared Packages
shared_app_config Free
- Tier
- Freeversion 1.2.6
- Command
archipelago generate shared_app_config- Generates
shared/app_config
- Used by
- app_scaffold, network_sdk, feature_flag_sdk, appsflyer_analytics_impl, mixpanel_analytics_impl, moengage_analytics_impl and 1 more
Centralized configuration package for environment variables and flavor management, using
enviedfor obfuscated compile-time env var injection, plus vendor-gatedAppEnvgetters 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
| Variable | Type | Default | Description |
|---|---|---|---|
| appName | string | MyApp | The name of your application |
| analyticsVendors | array (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. |
| featureFlagVendor | enum (flagr, remote_config, custom, none) | none | Feature 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. |
| isForMonorepo | boolean | true | Whether 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
archipelago generate shared_app_configNon-interactive (CI)
archipelago generate shared_app_config --config my_config.jsonGenerated Structure
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.yamlOnly .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:
@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:
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.flagrBaseUrlFlavor
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
dart run monorepo_toolkit env switch development
dart run build_runner build --delete-conflicting-outputs
flutter build apk --flavor developmentSee the Environment Sync guide for the full env switch/env init reference and CI integration.
Adding environment variables
- Add
@EnviedField()toenv.dart(or rundart run monorepo_toolkit env add MY_VAR). - Add the key to
.env.exampleand all.env.<flavor>files. - Run
dart run monorepo_toolkit env switch <current_flavor>. - 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.