ENVied: the best way to handle your environment variables in Flutter

ENVied: the best way to handle your environment variables in Flutter


3 min read

Hi everyone, in this post, I want to show you the best way to store environment variables in a Flutter project that I started to use some months ago in all of my projects after seeing it in this blog post from CodewithAndrea: How to Store API Keys in Flutter: --dart-define vs .env files.

In an application that communicates with external services, that needs to authenticate via API key or to configure particular settings we must set environment variables that must be kept as hidden as possible, especially those related to API keys, but rather conveniently to be used in our Flutter applications.

For all this, we are helped by the valid ENVied package that lets you create a convenient Dart class that maps the .env file. To install it we can add it to the pubspec.yaml file along with envied_generator and build_runner for the build step and generation of the Dart class:

  envied: ^0.3.0

  envied_generator: ^0.3.0
  build_runner: ^2.3.3

Now we can create an .env file inside our project where we can add all our environment variables like this:

GREETINGS="Hello world!"

Now we have to create a env.dart file where we can define our constants:

import 'package:envied/envied.dart';

part 'env.g.dart';

//Here you can specify the path to your .env file
//  relative to the project root
@Envied(path: '.env')
abstract class Env {
  //The ofuscate flag lets you make your variables more
  // secure through obfuscation
  @EnviedField(varName: 'GREETINGS', obfuscate: true)
  static final greetings = _Env.greetings;
  @EnviedField(varName: 'MY_NAME', obfuscate: true)
  static final myName = _Env.myName;

Now we can do the build step and let ENVied generate the class for us, so let's run:

flutter pub run build_runner build --delete-conflicting-outputs

ENVied will generate a file named env.g.dart alongside env.dart with pretty much this content:

part of 'env.dart';
// *****************************************************
// EnviedGenerator
// *****************************************************
class _Env {
  static const List<int> _enviedkeygreetings = [
    3271495377, 3997315090, 436058207, 3553787292, 3538777736,
    955590460, 3819871908, 4039201348, 2424541315, 3686169803,
    1299522498, 1263434759
  static const List<int> _envieddatagreetings = [
    3271495321, 3997315191, 436058163, 3553787376, 3538777831,
    955590428, 3819871955, 4039201323, 2424541425, 3686169767,
    1299522470, 1263434790
  static final greetings = String.fromCharCodes(
    List.generate(_envieddatagreetings.length, (i) => i, growable: false)
        .map((i) => _envieddatagreetings[i] ^ _enviedkeygreetings[i])
        .toList(growable: false),
  static const List<int> _enviedkeymyName = [
    3026637516, 1908999005, 3526437322, 2478128297, 2753058997,
    855764648, 1111676782
  static const List<int> _envieddatamyName = [
    3026637453, 1908998961, 3526437288, 2478128332, 2753059015,
    855764700, 1111676673
  static final myName = String.fromCharCodes(
    List.generate(_envieddatamyName.length, (i) => i, growable: false)
        .map((i) => _envieddatamyName[i] ^ _enviedkeymyName[i])
        .toList(growable: false),

Before proceeding it is good to exclude from version control the .env and env.g.dart files that contain all our variables, to do this simply add to the .gitignore file:


App Code

At this point, we can create a small example app that shows how to use our environment variables and call them within the code, so create a main.dart file with the following code:

import 'package:flutter/material.dart';

import 'env.dart';

void main() {
  runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'ENVied Demo',
      home: Scaffold(
        appBar: AppBar(
          title: const Text("ENVied Demo"),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
                "Hi, I'm ${Env.myName}",

As you can see we can call within the code of our app the environment variables we created simply with:

//Import the env class
import 'env.dart';

//Use variables

The result is something like this:


In this post, we saw how to secure our environment variables through obfuscation, how to exclude them from version control so they are not exposed in our repositories, and how to generate a Dart class that we can access throughout the code to conveniently use our variables. So we have all the requirements to start developing an app with a good degree of security.

Code strong, Alberto

Did you find this article valuable?

Support Alberto Bonacina by becoming a sponsor. Any amount is appreciated!