πΏ envified
Stop rebuilding. Start switching. β‘
Runtime environment magic for Flutter apps. No hot reload needed.
The Problem
You're a Flutter developer. Every time you need to test a different API endpointβlocal dev server, staging, productionβyou rebuild the app. With --dart-define flags. Or .env files baked into the binary. Or multiple entry points. It's tedious. It's error-prone. It breaks flow.
What if you could swap environments in 0.2 seconds? No rebuild. No compilation. Just tap, tap, done.
That's envified.
What is envified?
envified is a production-grade environment manager for Flutter that lives entirely at runtime.
- π Swap dev β prod in 200ms β no rebuild, no hot reload
- π Prod lock by default β prevent accidental data disasters
- π§ͺ Override any URL β test against local tunnels, PR branches, anywhere
- π Premium PIN gate β secure the debug panel with glassmorphic UI
- π Full audit trail β log every switch and URL change
- βοΈ Zero production overhead β stripped out completely in release builds
- π¨ Premium debug UI β dark-luxury design, fully customizable
It's not just a config switcher. It's enterprise-grade security meets developer quality of life.
Note
Security Note: While envified encrypts the active configuration state and overrides on the device (via Keychain/Keystore), the base .env files stored in your Flutter assets remain plaintext. Never store high-stakes production secrets directly in .env files; they should be fetched at runtime from a secure vault or used for non-sensitive configuration only.
πΈ See It In Action
π Zero-Config Auto-Discovery (v2.1.0+)
envified now automatically scans your assets/env/ directory for any .env.* files. No manual mapping required!
// No need to specify URLs β they're discovered automatically!
await EnvConfigService.instance.init();
// β
Finds .env.dev, .env.staging, .env.prod, .env.uat, etc.
// β
Extracts BASE_URL from each
// β
Auto-populates the UI
The debug panel automatically generates buttons for every discovered environment. A standalone .env file is treated as Production by default.
π¦ Features
| Feature | What It Does | Why You Care |
|---|---|---|
| Auto-Discovery | Scans assets for .env.* files |
Zero config; just add a file and it works |
| Tamper Detection | SHA-256 hashes .env* files |
Catch rogue config changes on rooted devices |
| Access Gate | Premium PIN dialog before opening panel | QA devices don't leak sensitive switches |
| Typed Getters | getBool(), getInt(), getUri(), getList() |
No more string parsing bugs |
| Lifecycle Hooks | onBeforeSwitch / onAfterSwitch callbacks |
Flush HTTP queues, log analytics, etc. |
| URL History | Last 5 URLs one-tap available | Faster testing against recent tunnels |
| Status Badge | Persistent [DEV] indicator in your app |
Never forget what env you're testing |
| Gesture Triggers | Tap N times, shake, or swipe edge to open | Customize to your preference |
| Audit Log | Encrypted log of every switch | "Who changed prod at 3pm?" |
Quick Start (3 Steps)
1οΈβ£ Install
dependencies:
envified: ^2.1.0
2οΈβ£ Add .env Files
Create in assets/env/:
# .env.dev
BASE_URL=https://dev.api.myapp.com
DEBUG=true
# .env.prod
BASE_URL=https://api.myapp.com
DEBUG=false
Register in pubspec.yaml:
flutter:
assets:
- assets/env/
3οΈβ£ Initialize
In main.dart, before runApp():
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await EnvConfigService.instance.init(
defaultEnv: Env.dev,
allowProdSwitch: false, // β οΈ Lock prod by default
verifyIntegrity: true, // π Detect tampering (Prod only)
);
runApp(const MyApp());
}
Wrap your app with the overlay:
MaterialApp(
builder: (context, child) => EnvifiedOverlay(
service: EnvConfigService.instance,
enabled: kDebugMode, // π« Hidden in production
gate: EnvGate(pin: '1234'), // π Secure PIN gate
child: child ?? const SizedBox.shrink(),
),
home: const MyApp(),
)
Core Usage Patterns
Reading Values
final svc = EnvConfigService.instance;
final name = svc.get('APP_NAME');
final timeout = svc.getInt('TIMEOUT', fallback: 30);
final debug = svc.getBool('DEBUG');
final apiUrl = svc.getUri('BASE_URL');
Reacting to Switches
EnvConfigService.current is a ValueNotifier.
EnvConfigService.instance.current.addListener(() {
final config = EnvConfigService.instance.current.value;
dio.options.baseUrl = config.baseUrl;
print('Active env: ${config.env.name}');
});
Security & Production Safety
π Production Lock
By default, allowProdSwitch: false locks the production environment. Once the app starts in a production-identified environment (e.g., via .env.prod), switching is disabled.
β Tamper Detection
When verifyIntegrity: true is set, envified computes a SHA-256 hash of your production .env files. If the files are modified (e.g., on a rooted device), it throws EnvifiedTamperException.
βοΈ Zero Production Overhead
All debug components (buttons, panels, gates) are wrapped in kDebugMode checks. Flutter's tree-shaker removes them entirely from release builds. Zero bytes added to your production IPA/APK.
π API Reference
Env (Class)
Replaced the enum with a dynamic class.
Env.dev,Env.staging,Env.prod(Standard constants)Env.fromFileName(name)(Factory for discovered files)env.isProduction(Boolean flag)
EnvConfigService
init(): Discover files and load state.switchTo(Env): Change environment at runtime.setBaseUrl(url): Override the current URL.current:ValueNotifier<EnvConfig>.
π€ Contributing
See CONTRIBUTING.md for details. Found a bug? Open an Issue!
Support the Project β
envified is 100% open source and free. If it saves you hours of rebuild time, consider supporting the maintainer:
βΉ20 β Support | βΉ100 β Production Use
π License
MIT Β© Appamania
Libraries
- envified
- envified β Runtime environment switching for Flutter.