🌿 envified

pub package pub points License: MIT Dart CI Buy me a Chai

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

Live demo: tap to switch


πŸš€ 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.