diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,11 @@
 ## MASTER
+## Dotenv 0.5.0.0
+
+* Add [dotenv-safe functionality](https://www.npmjs.com/package/dotenv-safe)
+* Add the `Config` type with options to override env variables, and setting the
+path for .env and .env.example files.
+* Changed `loadFile` function to get `Config` with the paths for the .env file
+and the .env.example file.
 
 ## Dotenv 0.4.0.0
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -43,6 +43,22 @@
 environment using standard functions from `System.Environment` such as
 `lookupEnv` and `getEnv`.
 
+### NOTE: Empty environment variables
+
+If you need to have empty environment variables in your configuration, you can
+use something like the code below:
+
+```haskell
+fromMaybe "" <$> lookupEnv "ENV_VAR"
+```
+
+Currently, `dotenv-hs` doesn't allow you to set empty environment variables,
+because of [setEnv](https://hackage.haskell.org/package/base-4.9.1.0/docs/System-Environment.html#v:setEnv)
+from our `System.Environment`. This is bug reported in [GHC ticket](https://ghc.haskell.org/trac/ghc/ticket/12494).
+We have had many [dicussions](https://github.com/stackbuilders/dotenv-hs/issues/48)
+about this. Fortunately, there is already some work for this issue in
+[GHC Phabricator](https://phabricator.haskell.org/D3726).
+
 ## Configuration
 
 The first argument to `loadFile` specifies whether you want to
@@ -65,15 +81,50 @@
 You can call dotenv from the command line in order to load settings
 from one or more dotenv file before invoking an executable:
 
-```
-dotenv -f mydotenvfile myprogram
+```shell
+$ dotenv -e mydotenvfile myprogram
 ```
 
 Aditionally you can pass arguments and flags to the program passed to
 Dotenv:
 
+```shell
+$ dotenv -e mydotenvfile myprogram -- --myflag myargument
 ```
-dotenv -f mydotenvfile myprogram -- --myflag myargument
+
+or:
+
+```shell
+$ dotenv -e mydotenvfile "myprogram --myflag myargument"
+```
+
+Also, you can use a `--example` flag to use [dotenv-safe functionality](https://www.npmjs.com/package/dotenv-safe)
+so that you can have a list of strict envs that should be defined in the environment
+or in your dotenv files before the execution of your program. For instance:
+
+```shell
+$ cat .env.example
+DOTENV=
+FOO=
+BAR=
+
+$ cat .env
+DOTENV=123
+
+$ echo $FOO
+123
+```
+
+This will fail:
+```shell
+$ dotenv -e .env --example .env.example "myprogram --myflag myargument"
+> dotenv: Missing env vars! Please, check (this/these) var(s) (is/are) set: BAR
+```
+
+This will succeed:
+```shell
+$ export BAR=123 # Or you can do something like: "echo 'BAR=123' >> .env"
+$ dotenv -e .env --example .env.example "myprogram --myflag myargument"
 ```
 
 Hint: The `env` program in most Unix-like environments prints out the
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP             #-}
+{-# LANGUAGE RecordWildCards #-}
 
 module Main where
 
@@ -8,36 +9,50 @@
 
 import Options.Applicative
 
-import Configuration.Dotenv (loadFile)
+import Control.Monad (void)
 
-import Control.Monad.IO.Class(MonadIO(..))
+import Configuration.Dotenv (loadFile)
+import Configuration.Dotenv.Types (Config(..))
 
 import System.Process (system)
 import System.Exit (exitWith)
 
 data Options = Options
-  { files    :: [String]
-  , overload :: Bool
-  , program  :: String
-  , args     :: [String]
+  { dotenvFiles        :: [String]
+  , dotenvExampleFiles :: [String]
+  , override           :: Bool
+  , program            :: String
+  , args               :: [String]
   } deriving (Show)
 
 main :: IO ()
-main = execParser opts >>= dotEnv
-  where
-    opts = info (helper <*> config)
-      ( fullDesc
-     <> progDesc "Runs PROGRAM after loading options from FILE"
-     <> header "dotenv - loads options from dotenv files" )
+main = do
+  Options{..} <- execParser opts
+  void $ loadFile Config
+    { configExamplePath = dotenvExampleFiles
+    , configOverride = override
+    , configPath = dotenvFiles
+    }
+  system (program ++ concatMap (" " ++) args) >>= exitWith
+    where
+      opts = info (helper <*> config)
+        ( fullDesc
+       <> progDesc "Runs PROGRAM after loading options from FILE"
+       <> header "dotenv - loads options from dotenv files" )
 
 config :: Parser Options
 config = Options
      <$> some (strOption (
-                  long "file"
+                  long "dotenv"
                   <> short 'f'
-                  <> metavar "FILE"
-                  <> help "File to read for options" ))
+                  <> metavar "DOTENV"
+                  <> help "File to read for environmental variables" ))
 
+     <*> many (strOption (
+                  long "example"
+                  <> metavar "DOTENV_EXAMPLE"
+                  <> help "File to read for needed environmental variables" ))
+
      <*> switch ( long "overload"
                   <> short 'o'
                   <> help "Specify this flag to override existing variables" )
@@ -46,10 +61,3 @@
 
      <*> many (argument str (metavar "ARG"))
 
-dotEnv :: MonadIO m => Options -> m ()
-dotEnv opts = liftIO $ do
-  mapM_ (loadFile (overload opts)) (files opts)
-  code <- system (program opts ++ programArguments)
-  exitWith code
-  where
-   programArguments = concatMap (" " ++) (args opts)
diff --git a/dotenv.cabal b/dotenv.cabal
--- a/dotenv.cabal
+++ b/dotenv.cabal
@@ -1,5 +1,5 @@
 name:                dotenv
-version:             0.4.0.0
+version:             0.5.0.0
 synopsis:            Loads environment variables from dotenv files
 homepage:            https://github.com/stackbuilders/dotenv-hs
 description:
@@ -72,6 +72,7 @@
                       , Configuration.Dotenv.Parse
                       , Configuration.Dotenv.ParsedVariable
                       , Configuration.Dotenv.Text
+                      , Configuration.Dotenv.Types
 
   build-depends:         base >=4.7 && <5.0
                        , base-compat >= 0.4
@@ -100,6 +101,7 @@
                        , Configuration.Dotenv.ParseSpec
                        , Configuration.Dotenv
                        , Configuration.Dotenv.Text
+                       , Configuration.Dotenv.Types
                        , Configuration.Dotenv.Parse
                        , Configuration.Dotenv.ParsedVariable
 
diff --git a/spec/Configuration/DotenvSpec.hs b/spec/Configuration/DotenvSpec.hs
--- a/spec/Configuration/DotenvSpec.hs
+++ b/spec/Configuration/DotenvSpec.hs
@@ -2,6 +2,7 @@
 
 module Configuration.DotenvSpec (main, spec) where
 
+import Configuration.Dotenv.Types (Config(..))
 import Configuration.Dotenv (load, loadFile, parseFile, onMissingFile)
 
 import Test.Hspec
@@ -52,33 +53,48 @@
 
       lookupEnv "foo" `shouldReturn` Just "new setting"
 
-  describe "loadFile" $ after_ (unsetEnv "DOTENV") $ do
+  describe "loadFile" $ after_ (mapM_ unsetEnv ["DOTENV" , "ANOTHER_ENV"]) $ do
     it "loads the configuration options to the environment from a file" $ do
       lookupEnv "DOTENV" `shouldReturn` Nothing
 
-      loadFile False "spec/fixtures/.dotenv"
+      loadFile $ Config ["spec/fixtures/.dotenv"] [] False
 
       lookupEnv "DOTENV" `shouldReturn` Just "true"
 
     it "respects predefined settings when overload is false" $ do
       setEnv "DOTENV" "preset"
 
-      loadFile False "spec/fixtures/.dotenv"
+      loadFile $ Config ["spec/fixtures/.dotenv"] [] False
 
       lookupEnv "DOTENV" `shouldReturn` Just "preset"
 
     it "overrides predefined settings when overload is true" $ do
       setEnv "DOTENV" "preset"
 
-      loadFile True "spec/fixtures/.dotenv"
+      loadFile $ Config ["spec/fixtures/.dotenv"] [] True
 
       lookupEnv "DOTENV" `shouldReturn` Just "true"
 
+    context "when the .env.example is present" $ do
+      let config = Config ["spec/fixtures/.dotenv"] ["spec/fixtures/.dotenv.example"] False
+
+      context "when the needed env vars are missing" $
+        it "should fail with an error call" $
+          loadFile config `shouldThrow` anyErrorCall
+
+      context "when the needed env vars are not missing" $
+        it "should succeed when loading all of the needed env vars" $ do
+          setEnv "ANOTHER_ENV" "hello"
+          loadFile config `shouldReturn` ()
+          lookupEnv "DOTENV" `shouldReturn` Just "true"
+          lookupEnv "UNICODE_TEST" `shouldReturn` Just "Manabí"
+          lookupEnv "ANOTHER_ENV" `shouldReturn` Just "hello"
+
   describe "parseFile" $ after_ (unsetEnv "DOTENV") $ do
     it "returns variables from a file without changing the environment" $ do
       lookupEnv "DOTENV" `shouldReturn` Nothing
 
-      (liftM head $ parseFile "spec/fixtures/.dotenv") `shouldReturn`
+      liftM head (parseFile "spec/fixtures/.dotenv") `shouldReturn`
         ("DOTENV", "true")
 
       lookupEnv "DOTENV" `shouldReturn` Nothing
@@ -99,9 +115,10 @@
   describe "onMissingFile" $ after_ (unsetEnv "DOTENV") $ do
     context "when target file is present" $
       it "loading works as usual" $ do
-        onMissingFile (loadFile True "spec/fixtures/.dotenv") (return ())
+        onMissingFile (loadFile $ Config ["spec/fixtures/.dotenv"] [] True) (return ())
         lookupEnv "DOTENV" `shouldReturn` Just "true"
+
     context "when target file is missing" $
       it "executes supplied handler instead" $
-        onMissingFile (True <$ loadFile True "spec/fixtures/foo") (return False)
+        onMissingFile (True <$ (loadFile $ Config ["spec/fixtures/foo"] [] True)) (return False)
           `shouldReturn` False
diff --git a/src/Configuration/Dotenv.hs b/src/Configuration/Dotenv.hs
--- a/src/Configuration/Dotenv.hs
+++ b/src/Configuration/Dotenv.hs
@@ -9,7 +9,8 @@
 --
 -- This module contains common functions to load and read dotenv files.
 
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP             #-}
+{-# LANGUAGE RecordWildCards #-}
 
 module Configuration.Dotenv
   ( load
@@ -18,18 +19,21 @@
   , onMissingFile )
  where
 
+import Control.Monad (liftM)
 import Configuration.Dotenv.Parse (configParser)
 import Configuration.Dotenv.ParsedVariable (interpolateParsedVariables)
+import Configuration.Dotenv.Types (Config(..))
 import Control.Monad.Catch
 import Control.Monad.IO.Class (MonadIO(..))
+import Data.List (union, intersectBy, unionBy)
 import System.Environment (lookupEnv)
 import System.IO.Error (isDoesNotExistError)
-import Text.Megaparsec (parse)
+import Text.Megaparsec (parse, parseErrorPretty)
 
 #if MIN_VERSION_base(4,7,0)
-import System.Environment (setEnv)
+import System.Environment (getEnvironment, setEnv)
 #else
-import System.Environment.Compat (setEnv)
+import System.Environment.Compat (getEnvironment, setEnv)
 #endif
 
 -- | Loads the given list of options into the environment. Optionally
@@ -41,14 +45,30 @@
   -> m ()
 load override = mapM_ (applySetting override)
 
--- | Loads the options in the given file to the environment. Optionally
--- override existing variables with values from Dotenv files.
-loadFile ::
-  MonadIO m =>
-  Bool        -- ^ Override existing settings?
-  -> FilePath -- ^ A file containing options to load into the environment
+-- | @loadFile@ parses the environment variables defined in the dotenv example
+-- file and checks if they are defined in the dotenv file or in the environment.
+-- It also allows to override the environment variables defined in the environment
+-- with the values defined in the dotenv file.
+loadFile
+  :: MonadIO m
+  => Config
   -> m ()
-loadFile override f = load override =<< parseFile f
+loadFile Config{..} = do
+  environment <- liftIO getEnvironment
+  readedVars <- concat `liftM` mapM parseFile configPath
+  neededVars <- concat `liftM` mapM parseFile configExamplePath
+  let coincidences = (environment `union` readedVars) `intersectEnvs` neededVars
+      cmpEnvs env1 env2 = fst env1 == fst env2
+      intersectEnvs = intersectBy cmpEnvs
+      unionEnvs = unionBy cmpEnvs
+      vars =
+        if (not . null) neededVars
+          then
+            if length neededVars == length coincidences
+              then readedVars `unionEnvs` neededVars
+              else error $ "Missing env vars! Please, check (this/these) var(s) (is/are) set:" ++ concatMap ((++) " " . fst) neededVars
+          else readedVars
+  mapM_ (applySetting configOverride) vars
 
 -- | Parses the given dotenv file and returns values /without/ adding them to
 -- the environment.
@@ -60,7 +80,7 @@
   contents <- liftIO $ readFile f
 
   case parse configParser f contents of
-    Left e        -> error $ "Failed to read file" ++ show e
+    Left e        -> error $ parseErrorPretty e
     Right options -> liftIO $ interpolateParsedVariables options
 
 applySetting :: MonadIO m => Bool -> (String, String) -> m ()
diff --git a/src/Configuration/Dotenv/Types.hs b/src/Configuration/Dotenv/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Configuration/Dotenv/Types.hs
@@ -0,0 +1,34 @@
+{- |
+-- Module      :  Configuration.Dotenv.Types
+-- Copyright   :  © 2015–2017 Stack Builders Inc.
+-- License     :  MIT
+--
+-- Maintainer  :  Stack Builders <hackage@stackbuilders.com>
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- Provides the types with extra options for loading a dotenv file.
+-}
+
+module Configuration.Dotenv.Types
+  ( Config(..)
+  , defaultConfig
+  )
+  where
+
+-- | Configuration Data Types with extra options for executing dotenv.
+data Config = Config
+  { configPath        :: [FilePath] -- ^ The paths for the .env files
+  , configExamplePath :: [FilePath] -- ^ The paths for the .env.example files
+  , configOverride    :: Bool     -- ^ Flag to allow override env variables
+  } deriving (Eq, Show)
+
+-- | Default configuration. Use .env file without .env.example strict envs and
+-- without overriding.
+defaultConfig :: Config
+defaultConfig =
+  Config
+    { configExamplePath = []
+    , configOverride = False
+    , configPath = [ ".env" ]
+    }
