Setting Up Shared App Config
What you'll learn
- Generating the shared config package with envied integration
- Managing environment variables across flavors (dev, staging, production)
- Using compile-time obfuscated env var injection
- Accessing config values throughout your monorepo
Prerequisites
- An existing Archipelago monorepo (see Monorepo Scaffolding)
Step 1: Generate the Shared App Config
bash
archipelago generate shared_app_configYou will be prompted for:
- appName —
MyApp(must match your monorepo app name) - isForMonorepo —
true
Or use a config file:
json
{
"appName": "MyApp",
"isForMonorepo": true
}bash
archipelago generate shared_app_config --config config.jsonStep 2: Understand the Generated Structure
shared/
└── app_config/
├── lib/src/
│ ├── app_config.dart # Main config class
│ ├── env/
│ │ ├── env.dart # @Envied annotated class
│ │ └── env.g.dart # Generated (obfuscated values)
│ └── flavor.dart # Flavor enum (dev, staging, prod)
├── .env.development # Dev environment variables
├── .env.staging # Staging environment variables
├── .env.production # Production environment variables
└── pubspec.yamlStep 3: Define Your Environment Variables
Edit the .env.* files for each flavor:
bash
# .env.development
BASE_URL=https://api-dev.myapp.com
SENTRY_DSN=
ENABLE_LOGGING=true
# .env.production
BASE_URL=https://api.myapp.com
SENTRY_DSN=https://key@sentry.io/123
ENABLE_LOGGING=falseStep 4: Add Variables to the Envied Class
dart
// app_config/lib/src/env/env.dart
@Envied(path: '.env', obfuscate: true)
abstract class Env {
@EnviedField(varName: 'BASE_URL')
static const String baseUrl = _Env.baseUrl;
@EnviedField(varName: 'SENTRY_DSN', defaultValue: '')
static const String sentryDsn = _Env.sentryDsn;
@EnviedField(varName: 'ENABLE_LOGGING')
static const bool enableLogging = _Env.enableLogging;
}Run code generation after adding fields:
bash
dart run build_runner build --delete-conflicting-outputsStep 5: Use Config in Your App
dart
// Access from anywhere in the monorepo
import 'package:app_config/app_config.dart';
final apiUrl = Env.baseUrl;
final dsn = Env.sentryDsn;Why Envied Over dart-define
| Approach | Downside |
|---|---|
--dart-define | Values visible in process list, no obfuscation |
envied | Compile-time injection with string obfuscation |
Envied generates obfuscated Dart code so secrets are not stored as plain strings in the compiled binary.
Common Customizations
| Customization | Where to Change |
|---|---|
| Add new env vars | .env.* files + env.dart |
| Change flavors | flavor.dart enum |
| Add per-feature config | Create feature-specific @Envied classes |
| CI/CD secrets | Inject .env files from CI secret store |
Next Steps
- Set up Shared Dependencies for centralized package management
- Configure build_prepare for flavor-based builds