diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@
 * Setting an environment variable called `AWESOMEAPP_SERVER_PORT=5555`
 * In a `config/dev.properties` file, you can have `server.port=5555`
 
-And you may also get that value from different configuration providers like
+And you may also get that value from different configuration sources like
 redis, json file, dhall file or whichever you may need.
 
 ## Example 2: many different values with defaults
@@ -110,14 +110,14 @@
 * `--hedis.host=redis.example.com`: set hedis' connection host to `redis.example.com`
 
 
-## Existing providers
+## Existing sources
 
-Providers usually incur in many dependencies so they are split into different
+Sources usually incur in many dependencies so they are split into different
 packages
 
-* *[Json](https://hackage.haskell.org/package/conferer-provider-json)* (depends on `aeson`)
-* *[Dhall](https://hackage.haskell.org/package/conferer-provider-dhall)* (depends on `dhall`)
-* *[Yaml](https://hackage.haskell.org/package/conferer-provider-yaml)* (depends on `yaml`) 
+* *[Json](https://hackage.haskell.org/package/conferer-source-json)* (depends on `aeson`)
+* *[Dhall](https://hackage.haskell.org/package/conferer-source-dhall)* (depends on `dhall`)
+* *[Yaml](https://hackage.haskell.org/package/conferer-source-yaml)* (depends on `yaml`) 
 
 ## Existing FromConfig instances
 
@@ -131,17 +131,17 @@
 
 ## Utilities
 
-There are as well some utilities to change providers:
+There are as well some utilities to change sources:
 
-* `Conferer.Provider.Namespace`: All keys must be namespaced and the namespace
+* `Conferer.Source.Namespace`: All keys must be namespaced and the namespace
   is striped for lookup
-* `Conferer.Provider.Mapped`: Using a map key to maybe key you can change the
+* `Conferer.Source.Mapped`: Using a map key to maybe key you can change the
   name of a key or even hiding some key
-* `Conferer.Provider.Simple`: Get keys from a hardcoded map key to string
+* `Conferer.Source.Simple`: Get keys from a hardcoded map key to string
 
 ## Future maybe things
 
 * Interpolate keys with other keys: `{a: "db", b: "${a}_thing"}`, getting `b`
   will give `"db_thing"` (maybe) even in different levels of configuration
-* A LOT of providers
+* A LOT of sources
 * A LOT of `FromConfig` implementations
diff --git a/conferer.cabal b/conferer.cabal
--- a/conferer.cabal
+++ b/conferer.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.18
 
--- This file has been generated from package.yaml by hpack version 0.31.2.
+-- This file has been generated from package.yaml by hpack version 0.33.0.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: e9e6edef27397421e3ed20cd7b4269e086ded2fc7fd679dac79be16cf923d188
+-- hash: 27fd2a5bad0744bb410d47e23efe3ef9a76a0bb35bd073e397f8f5f6c5c9a796
 
 name:           conferer
-version:        0.3.0.0
+version:        0.4.0.0
 synopsis:       Configuration management library
 
 description:    Library to abstract the parsing of many haskell config values from different config sources
@@ -28,14 +28,14 @@
       Conferer
       Conferer.Core
       Conferer.FromConfig.Basics
-      Conferer.Provider.CLIArgs
-      Conferer.Provider.Env
-      Conferer.Provider.Files
-      Conferer.Provider.Mapping
-      Conferer.Provider.Namespaced
-      Conferer.Provider.Null
-      Conferer.Provider.PropertiesFile
-      Conferer.Provider.Simple
+      Conferer.Source.CLIArgs
+      Conferer.Source.Env
+      Conferer.Source.Files
+      Conferer.Source.Mapping
+      Conferer.Source.Namespaced
+      Conferer.Source.Null
+      Conferer.Source.PropertiesFile
+      Conferer.Source.Simple
       Conferer.Types
   other-modules:
       Paths_conferer
@@ -56,13 +56,13 @@
   other-modules:
       Conferer.FromConfig.BasicsSpec
       Conferer.GenericsSpec
-      Conferer.Provider.ArgsSpec
-      Conferer.Provider.EnvSpec
-      Conferer.Provider.MappingSpec
-      Conferer.Provider.NamespacedSpec
-      Conferer.Provider.NullSpec
-      Conferer.Provider.PropertiesFileSpec
-      Conferer.Provider.SimpleSpec
+      Conferer.Source.ArgsSpec
+      Conferer.Source.EnvSpec
+      Conferer.Source.MappingSpec
+      Conferer.Source.NamespacedSpec
+      Conferer.Source.NullSpec
+      Conferer.Source.PropertiesFileSpec
+      Conferer.Source.SimpleSpec
       ConfererSpec
       Paths_conferer
   hs-source-dirs:
diff --git a/src/Conferer.hs b/src/Conferer.hs
--- a/src/Conferer.hs
+++ b/src/Conferer.hs
@@ -50,23 +50,23 @@
   -- (eg: @warp@) you can get anything that implements 'FromConfig' (like
   -- 'Warp.Settings')
   --
-  -- Internally a 'Config' is made of many 'Provider's which have a simpler
+  -- Internally a 'Config' is made of many 'Source's which have a simpler
   -- interface:
   --
   -- @
-  -- 'getKeyInProvider' :: Provider -> Key -> IO (Maybe Text)
+  -- 'getKeyInSource' :: Source -> Key -> IO (Maybe Text)
   -- @
   --
-  -- Most configuration providers can be abstracted away as Map String String,
+  -- Most configuration sources can be abstracted away as Map String String,
   -- and they can use whatever logic they want to turn conferer keys (a list of
-  -- strings) into a place to look for a string, (for example the env provider
+  -- strings) into a place to look for a string, (for example the env source
   -- requires a string to namespace the env vars that can affect the
   -- configuration)
   --
-  -- Once you have your 'Provider' you can add it to a 'Config' using the
-  -- 'addProvider' function. One final note: each provider has a different
-  -- priority, which depends on when is was added to the config ('Provider's
-  -- added later have lower priority) so the config searches keys in providers
+  -- Once you have your 'Source' you can add it to a 'Config' using the
+  -- 'addSource' function. One final note: each source has a different
+  -- priority, which depends on when is was added to the config ('Source's
+  -- added later have lower priority) so the config searches keys in sources
   -- in the same order they were added.
 
   module Conferer.Types
@@ -75,14 +75,14 @@
   , defaultConfigWithDefaults
   , Key(..)
 
-  -- * Providers
-  , module Conferer.Provider.Env
-  , module Conferer.Provider.Simple
-  , module Conferer.Provider.Namespaced
-  , module Conferer.Provider.Mapping
-  , module Conferer.Provider.CLIArgs
-  , module Conferer.Provider.Null
-  , module Conferer.Provider.PropertiesFile
+  -- * Sources
+  , module Conferer.Source.Env
+  , module Conferer.Source.Simple
+  , module Conferer.Source.Namespaced
+  , module Conferer.Source.Mapping
+  , module Conferer.Source.CLIArgs
+  , module Conferer.Source.Null
+  , module Conferer.Source.PropertiesFile
   -- * Re-Exports
   , (&)
   ) where
@@ -90,15 +90,15 @@
 import           Data.Text (Text)
 import           Data.Function ((&))
 
-import           Conferer.Core (emptyConfig, addProvider, getFromConfig, getFromRootConfig, getFromConfigWithDefault, safeGetFromConfig, safeGetFromConfigWithDefault, getKey, unsafeGetKey, (/.), withDefaults)
-import           Conferer.Types (Config, Key(..), ProviderCreator, Provider(..), DefaultConfig(..), FromConfig(..))
-import           Conferer.Provider.Env
-import           Conferer.Provider.Simple
-import           Conferer.Provider.Namespaced
-import           Conferer.Provider.Mapping
-import           Conferer.Provider.CLIArgs
-import           Conferer.Provider.Null
-import           Conferer.Provider.PropertiesFile
+import           Conferer.Core (emptyConfig, addSource, getFromConfig, getFromRootConfig, getFromConfigWithDefault, safeGetFromConfig, safeGetFromConfigWithDefault, getKey, unsafeGetKey, (/.), withDefaults)
+import           Conferer.Types (Config, Key(..), SourceCreator, Source(..), DefaultConfig(..), FromConfig(..))
+import           Conferer.Source.Env
+import           Conferer.Source.Simple
+import           Conferer.Source.Namespaced
+import           Conferer.Source.Mapping
+import           Conferer.Source.CLIArgs
+import           Conferer.Source.Null
+import           Conferer.Source.PropertiesFile
 
 -- | Default config which reads from command line arguments, env vars and
 -- property files
@@ -111,7 +111,7 @@
 defaultConfigWithDefaults :: Text -> [(Key, Text)] -> IO Config
 defaultConfigWithDefaults appName configMap =
   pure (emptyConfig & withDefaults configMap)
-  >>= addProvider (mkCLIArgsProvider)
-  >>= addProvider (mkEnvProvider appName)
-  >>= addProvider (mkPropertiesFileProvider)
+  >>= addSource (mkCLIArgsSource)
+  >>= addSource (mkEnvSource appName)
+  >>= addSource (mkPropertiesFileSource)
 
diff --git a/src/Conferer/Core.hs b/src/Conferer/Core.hs
--- a/src/Conferer/Core.hs
+++ b/src/Conferer/Core.hs
@@ -10,22 +10,22 @@
 import           Data.Typeable (Typeable, Proxy(..), typeRep)
 import           Control.Exception (try, throw, throwIO, evaluate)
 
-import           Conferer.Provider.Simple
+import           Conferer.Source.Simple
 import           Conferer.Types
 
 -- | Most Basic function to interact directly with a 'Config'. It always returns
 --   'Text' in the case of success and implements the logic to traverse
---   providers inside the 'Config'.
+--   sources inside the 'Config'.
 getKey :: Key -> Config -> IO (Maybe Text)
 getKey k config =
-  go $ providers config ++ [mkPureMapProvider (defaults config)]
+  go $ sources config ++ [mkPureMapSource (defaults config)]
   where
     go [] = return Nothing
-    go (provider:providers) = do
-      res <- getKeyInProvider provider k
+    go (source:sources) = do
+      res <- getKeyInSource source k
       case res of
         Just t -> return $ Just t
-        Nothing -> go providers
+        Nothing -> go sources
 
 
 -- | Fetch a value from a config under some specific key that's parsed using the 'FromConfig'
@@ -93,20 +93,20 @@
 withDefaults configMap config =
   config { defaults = Map.fromList configMap }
 
--- | Instantiate a 'ProviderCreator' using the 'emptyConfig'
-mkStandaloneProvider :: ProviderCreator -> IO Provider
-mkStandaloneProvider mkProvider =
-  mkProvider emptyConfig
+-- | Instantiate a 'SourceCreator' using the 'emptyConfig'
+mkStandaloneSource :: SourceCreator -> IO Source
+mkStandaloneSource mkSource =
+  mkSource emptyConfig
 
 
--- | Instantiate a 'Provider' using an 'ProviderCretor' and a 'Config' and add
+-- | Instantiate a 'Source' using an 'SourceCretor' and a 'Config' and add
 --   to the config
-addProvider :: ProviderCreator -> Config -> IO Config
-addProvider mkProvider config = do
-  newProvider <- mkProvider config
+addSource :: SourceCreator -> Config -> IO Config
+addSource mkSource config = do
+  newSource <- mkSource config
   return $
     config
-    { providers = providers config ++ [ newProvider ]
+    { sources = sources config ++ [ newSource ]
     }
 
 -- | Same as 'getKey' but it throws if the 'Key' isn't found
diff --git a/src/Conferer/Provider/CLIArgs.hs b/src/Conferer/Provider/CLIArgs.hs
deleted file mode 100644
--- a/src/Conferer/Provider/CLIArgs.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-module Conferer.Provider.CLIArgs
-  (
-    -- * Command line arguments Provider
-    -- | This provider provides keys from the command line arguments passed into
-    -- the program. It only accepts arguments with @--@ and an equals, for
-    -- example: @./awesomeapp --warp.port=5000@
-    mkCLIArgsProvider
-    , mkCLIArgsProvider'
-    , parseArgsIntoKeyValue
-  )
-where
-
-import           Data.Text (Text)
-import qualified Data.Text as Text
-import           Data.Maybe (mapMaybe)
-import           Data.String (fromString)
-import           System.Environment (getArgs)
-
-import Conferer.Types
-import Conferer.Provider.Simple
-
-
--- | Create a 'ProviderCreator' for CLIArgs from a argument list
-mkCLIArgsProvider' :: [String] -> ProviderCreator
-mkCLIArgsProvider' args = \config -> do
-  let configMap = parseArgsIntoKeyValue args
-  mkMapProvider configMap config
-
--- | Same as 'mkCLIArgsProvider'' but using 'getArgs' to provide the argument
--- list
-mkCLIArgsProvider :: ProviderCreator
-mkCLIArgsProvider = \config -> do
-  args <- getArgs
-  mkCLIArgsProvider' args config
-
--- | Parse an argument list into a dictionary suitable for a 'Provider'
-parseArgsIntoKeyValue :: [String] -> [(Key, Text)]
-parseArgsIntoKeyValue =
-  fmap (\(k, s) -> (fromString $ Text.unpack k, s)) .
-  fmap (\s -> fmap (Text.drop 1) $ Text.breakOn "=" s).
-  mapMaybe (Text.stripPrefix "--") .
-  takeWhile (/= "--") .
-  fmap Text.pack
diff --git a/src/Conferer/Provider/Env.hs b/src/Conferer/Provider/Env.hs
deleted file mode 100644
--- a/src/Conferer/Provider/Env.hs
+++ /dev/null
@@ -1,67 +0,0 @@
-module Conferer.Provider.Env
-  (
--- * Env Provider
--- | This 'Provider' provides config values from env vars given a prefix that's
--- used to avoid colliding with different system configuration
---
--- For example if you use the 'Prefix' "awesomeapp" and get the 'Key'
--- "warp.port" this provider will try to lookup the env var called
--- @AWESOMEAPP_WARP_PORT@.
-
--- * Usage
--- | To use this provider simply choose a prefix and add it using the
--- 'addProvider' function like:
---
--- @
--- config & 'addProvider' ('mkEnvProvider' "awesomeapp")
--- @
-    mkEnvProvider
-    , mkEnvProvider'
-    , Prefix
-    , LookupEnvFunc
-    , keyToEnvVar
-  ) where
-
-
-import           Data.Text (Text)
-import qualified Data.Text as Text
-import qualified System.Environment as System
-
-import           Conferer.Types
-
--- | 'ProviderCreator' for env 'Provider' that uses the real 'System.lookupEnv'
--- function
-mkEnvProvider :: Prefix -> ProviderCreator
-mkEnvProvider prefix =
-  mkEnvProvider' System.lookupEnv prefix
-
--- | 'ProviderCreator' for env 'Provider' that allows parameterizing the
--- function used to lookup for testing
-mkEnvProvider' :: LookupEnvFunc -> Prefix -> ProviderCreator
-mkEnvProvider' lookupEnv prefix = \_config ->
-  return $
-  Provider
-  { getKeyInProvider = \k -> do
-      let envVarName = Text.unpack $ keyToEnvVar prefix k
-      fmap Text.pack <$> lookupEnv envVarName
-  }
-
--- | Type alias for the function to lookup env vars
-type LookupEnvFunc = String -> IO (Maybe String)
-
-
--- | A text to namespace env vars
-type Prefix = Text
-
--- | Get the env name from a prefix and a key by uppercasing and
--- intercalating underscores
---
--- >>> keyToEnVar "awesomeapp" "warp.port"
--- "AWESOMEAPP_WARP_PORT"
-keyToEnvVar :: Prefix -> Key -> Text
-keyToEnvVar prefix (Path keys) =
-  Text.toUpper
-  $ Text.intercalate "_"
-  $ filter (/= mempty)
-  $ prefix : keys
-
diff --git a/src/Conferer/Provider/Files.hs b/src/Conferer/Provider/Files.hs
deleted file mode 100644
--- a/src/Conferer/Provider/Files.hs
+++ /dev/null
@@ -1,21 +0,0 @@
-module Conferer.Provider.Files where
-
-import qualified Data.Text as Text
-import           Data.Maybe (fromMaybe)
-
-import           Conferer.Types
-import           Conferer.FromConfig.Basics ()
-
-fromRight :: a -> Either e a -> a
-fromRight a (Left _) = a
-fromRight _ (Right a) = a
-
-getFilePathFromEnv :: Config -> String -> IO FilePath
-getFilePathFromEnv config extension = do
-  env <- updateFromConfig "env" config "development"
-  return $ mconcat
-    [ "config/"
-    , Text.unpack env
-    , "."
-    , extension
-    ]
diff --git a/src/Conferer/Provider/Mapping.hs b/src/Conferer/Provider/Mapping.hs
deleted file mode 100644
--- a/src/Conferer/Provider/Mapping.hs
+++ /dev/null
@@ -1,34 +0,0 @@
-module Conferer.Provider.Mapping
-  (
-    -- * Namespaced higher-order provider
-    -- | This provider takes a provider and returns a new provider that
-    -- always transforms the key according to either a function for
-    -- 'mkMappingProvider'' or a 'Map' for 'mkMappingProvider'
-    mkMappingProvider
-    , mkMappingProvider'
-  )
-where
-
-import           Data.Map (Map)
-import qualified Data.Map as Map
-
-import           Conferer.Types
-
--- | Create a 'ProviderCreator' using a function to transform the supplied keys
--- and another 'ProviderCreator'
-mkMappingProvider' :: (Key -> Maybe Key) -> ProviderCreator -> ProviderCreator
-mkMappingProvider' mapper providerCreator config = do
-  configProvider <- providerCreator config
-
-  return $ Provider
-    { getKeyInProvider = \k -> do
-        case mapper k of
-          Just newKey -> getKeyInProvider configProvider newKey
-          Nothing -> return Nothing
-    }
-
--- | Create a 'ProviderCreator' using a 'Map' 'Key' 'Key' to transform the supplied keys
--- and another 'ProviderCreator'
-mkMappingProvider :: Map Key Key -> ProviderCreator -> ProviderCreator
-mkMappingProvider configMap configProvider =
-  mkMappingProvider' (`Map.lookup` configMap) configProvider
diff --git a/src/Conferer/Provider/Namespaced.hs b/src/Conferer/Provider/Namespaced.hs
deleted file mode 100644
--- a/src/Conferer/Provider/Namespaced.hs
+++ /dev/null
@@ -1,23 +0,0 @@
-module Conferer.Provider.Namespaced
-  (
-    -- * Namespaced higher-order provider
-    -- | This provider takes a provider and returns a new provider that
-    -- always checks that the 'Key' given always starts with certain 'Key'
-    -- and then strips that prefix before consulting its inner Provider
-    mkNamespacedProvider
-  ) where
-
-import           Data.List (stripPrefix)
-
-import           Conferer.Types
-
--- | Create a 'ProviderCreator' from a prefix and another 'ProviderCreator'
-mkNamespacedProvider :: Key -> ProviderCreator -> ProviderCreator
-mkNamespacedProvider (Path key) configCreator = \config -> do
-  configProvider <- configCreator config
-  return $ Provider
-    { getKeyInProvider = \(Path k) -> do
-        case stripPrefix key k of
-          Just newKey -> getKeyInProvider configProvider (Path newKey)
-          Nothing -> return Nothing
-    }
diff --git a/src/Conferer/Provider/Null.hs b/src/Conferer/Provider/Null.hs
deleted file mode 100644
--- a/src/Conferer/Provider/Null.hs
+++ /dev/null
@@ -1,18 +0,0 @@
-module Conferer.Provider.Null
-  (
-    -- * Does Nothing Provider
-    -- | The stub provider that never has a key
-    mkNullProvider
-  )
-where
-
-import           Conferer.Types
-
--- | Create a null 'Provider'
-mkNullProvider :: ProviderCreator
-mkNullProvider _config =
-  return $ Provider
-  { getKeyInProvider =
-      \_k -> do
-        return Nothing
-  }
diff --git a/src/Conferer/Provider/PropertiesFile.hs b/src/Conferer/Provider/PropertiesFile.hs
deleted file mode 100644
--- a/src/Conferer/Provider/PropertiesFile.hs
+++ /dev/null
@@ -1,54 +0,0 @@
-module Conferer.Provider.PropertiesFile where
-
-import           Data.Text (Text)
-import           Data.Function ((&))
-import           System.Directory (doesFileExist)
-import           Data.Maybe (catMaybes)
-import qualified Data.Text as Text
-import qualified Data.Text.IO as Text
-
-import           Conferer.Types
-import           Conferer.Provider.Files
-import           Conferer.Provider.Null
-import           Conferer.Provider.Simple
-
--- | 'ProviderCreator' for properties file 'Provider' that read from a
--- config file in @config/{env}.properties@ and parses it as a properties
--- file with @some.key=a value@ lines
-mkPropertiesFileProvider :: ProviderCreator
-mkPropertiesFileProvider = \config -> do
-  filePath <- getFilePathFromEnv config "properties"
-  fileExists <- doesFileExist filePath
-  if fileExists
-    then do
-      fileContent <- Text.readFile filePath
-      mkPropertiesFileProvider' fileContent config
-    else do
-      mkNullProvider config
-
-
--- | 'ProviderCreator' for properties file 'Provider' that only parses a
--- given 'Text' as a properties file
-mkPropertiesFileProvider' :: Text -> ProviderCreator
-mkPropertiesFileProvider' fileContent =
-  \config -> do
-    let keyValues =
-          fileContent
-          & Text.lines
-          & fmap lineToKeyValue
-          & catMaybes
-    mkMapProvider keyValues config
-
-
--- | Transform a line into a key/value pair (or not)
-lineToKeyValue :: Text -> Maybe (Key, Text)
-lineToKeyValue line =
-  Text.breakOn "=" line
-  & (\(rawKey, rawValue) ->
-      case Text.stripPrefix "=" rawValue of
-        Just value ->
-          Just (Path $ Text.splitOn "." rawKey, value)
-        Nothing ->
-          Nothing
-    )
-
diff --git a/src/Conferer/Provider/Simple.hs b/src/Conferer/Provider/Simple.hs
deleted file mode 100644
--- a/src/Conferer/Provider/Simple.hs
+++ /dev/null
@@ -1,34 +0,0 @@
-module Conferer.Provider.Simple
-  (
-    -- * Simple Provider
-    -- | This provider provides values from a hardcoded Map passed at creation
-    -- time that can not be changed afterwards, it's mostly used as a necessary
-    -- utility
-    mkMapProvider
-  , mkMapProvider'
-  , mkPureMapProvider
-  ) where
-
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Text (Text)
-
-import           Conferer.Types
-
--- | Make a 'ProviderCreator' from a 'Map'
-mkMapProvider' :: Map Key Text -> ProviderCreator
-mkMapProvider' configMap _config =
-  return $ mkPureMapProvider configMap
-
--- | Make a 'Provider' from a 'Map'
-mkPureMapProvider :: Map Key Text -> Provider
-mkPureMapProvider configMap =
-  Provider
-    { getKeyInProvider =
-      \k -> do
-        return $ Map.lookup k configMap
-    }
-
--- | Make a 'Provider' from 'List' of 'Key', 'Text' pairs
-mkMapProvider :: [(Key, Text)] -> ProviderCreator
-mkMapProvider = mkMapProvider' . Map.fromList
diff --git a/src/Conferer/Source/CLIArgs.hs b/src/Conferer/Source/CLIArgs.hs
new file mode 100644
--- /dev/null
+++ b/src/Conferer/Source/CLIArgs.hs
@@ -0,0 +1,43 @@
+module Conferer.Source.CLIArgs
+  (
+    -- * Command line arguments Source
+    -- | This source provides keys from the command line arguments passed into
+    -- the program. It only accepts arguments with @--@ and an equals, for
+    -- example: @./awesomeapp --warp.port=5000@
+    mkCLIArgsSource
+    , mkCLIArgsSource'
+    , parseArgsIntoKeyValue
+  )
+where
+
+import           Data.Text (Text)
+import qualified Data.Text as Text
+import           Data.Maybe (mapMaybe)
+import           Data.String (fromString)
+import           System.Environment (getArgs)
+
+import Conferer.Types
+import Conferer.Source.Simple
+
+
+-- | Create a 'SourceCreator' for CLIArgs from a argument list
+mkCLIArgsSource' :: [String] -> SourceCreator
+mkCLIArgsSource' args = \config -> do
+  let configMap = parseArgsIntoKeyValue args
+  mkMapSource configMap config
+
+-- | Same as 'mkCLIArgsSource'' but using 'getArgs' to provide the argument
+-- list
+mkCLIArgsSource :: SourceCreator
+mkCLIArgsSource = \config -> do
+  args <- getArgs
+  mkCLIArgsSource' args config
+
+-- | Parse an argument list into a dictionary suitable for a 'Source'
+parseArgsIntoKeyValue :: [String] -> [(Key, Text)]
+parseArgsIntoKeyValue =
+  fmap (\(k, s) -> (fromString $ Text.unpack k, s)) .
+  fmap (\s -> fmap (Text.drop 1) $ Text.breakOn "=" s).
+  mapMaybe (Text.stripPrefix "--") .
+  takeWhile (/= "--") .
+  fmap Text.pack
diff --git a/src/Conferer/Source/Env.hs b/src/Conferer/Source/Env.hs
new file mode 100644
--- /dev/null
+++ b/src/Conferer/Source/Env.hs
@@ -0,0 +1,67 @@
+module Conferer.Source.Env
+  (
+-- * Env Source
+-- | This 'Source' provides config values from env vars given a prefix that's
+-- used to avoid colliding with different system configuration
+--
+-- For example if you use the 'Prefix' "awesomeapp" and get the 'Key'
+-- "warp.port" this source will try to lookup the env var called
+-- @AWESOMEAPP_WARP_PORT@.
+
+-- * Usage
+-- | To use this source simply choose a prefix and add it using the
+-- 'addSource' function like:
+--
+-- @
+-- config & 'addSource' ('mkEnvSource' "awesomeapp")
+-- @
+    mkEnvSource
+    , mkEnvSource'
+    , Prefix
+    , LookupEnvFunc
+    , keyToEnvVar
+  ) where
+
+
+import           Data.Text (Text)
+import qualified Data.Text as Text
+import qualified System.Environment as System
+
+import           Conferer.Types
+
+-- | 'SourceCreator' for env 'Source' that uses the real 'System.lookupEnv'
+-- function
+mkEnvSource :: Prefix -> SourceCreator
+mkEnvSource prefix =
+  mkEnvSource' System.lookupEnv prefix
+
+-- | 'SourceCreator' for env 'Source' that allows parameterizing the
+-- function used to lookup for testing
+mkEnvSource' :: LookupEnvFunc -> Prefix -> SourceCreator
+mkEnvSource' lookupEnv prefix = \_config ->
+  return $
+  Source
+  { getKeyInSource = \k -> do
+      let envVarName = Text.unpack $ keyToEnvVar prefix k
+      fmap Text.pack <$> lookupEnv envVarName
+  }
+
+-- | Type alias for the function to lookup env vars
+type LookupEnvFunc = String -> IO (Maybe String)
+
+
+-- | A text to namespace env vars
+type Prefix = Text
+
+-- | Get the env name from a prefix and a key by uppercasing and
+-- intercalating underscores
+--
+-- >>> keyToEnVar "awesomeapp" "warp.port"
+-- "AWESOMEAPP_WARP_PORT"
+keyToEnvVar :: Prefix -> Key -> Text
+keyToEnvVar prefix (Path keys) =
+  Text.toUpper
+  $ Text.intercalate "_"
+  $ filter (/= mempty)
+  $ prefix : keys
+
diff --git a/src/Conferer/Source/Files.hs b/src/Conferer/Source/Files.hs
new file mode 100644
--- /dev/null
+++ b/src/Conferer/Source/Files.hs
@@ -0,0 +1,21 @@
+module Conferer.Source.Files where
+
+import qualified Data.Text as Text
+import           Data.Maybe (fromMaybe)
+
+import           Conferer.Types
+import           Conferer.FromConfig.Basics ()
+
+fromRight :: a -> Either e a -> a
+fromRight a (Left _) = a
+fromRight _ (Right a) = a
+
+getFilePathFromEnv :: Config -> String -> IO FilePath
+getFilePathFromEnv config extension = do
+  env <- updateFromConfig "env" config "development"
+  return $ mconcat
+    [ "config/"
+    , Text.unpack env
+    , "."
+    , extension
+    ]
diff --git a/src/Conferer/Source/Mapping.hs b/src/Conferer/Source/Mapping.hs
new file mode 100644
--- /dev/null
+++ b/src/Conferer/Source/Mapping.hs
@@ -0,0 +1,34 @@
+module Conferer.Source.Mapping
+  (
+    -- * Namespaced higher-order source
+    -- | This source takes a source and returns a new source that
+    -- always transforms the key according to either a function for
+    -- 'mkMappingSource'' or a 'Map' for 'mkMappingSource'
+    mkMappingSource
+    , mkMappingSource'
+  )
+where
+
+import           Data.Map (Map)
+import qualified Data.Map as Map
+
+import           Conferer.Types
+
+-- | Create a 'SourceCreator' using a function to transform the supplied keys
+-- and another 'SourceCreator'
+mkMappingSource' :: (Key -> Maybe Key) -> SourceCreator -> SourceCreator
+mkMappingSource' mapper sourceCreator config = do
+  configSource <- sourceCreator config
+
+  return $ Source
+    { getKeyInSource = \k -> do
+        case mapper k of
+          Just newKey -> getKeyInSource configSource newKey
+          Nothing -> return Nothing
+    }
+
+-- | Create a 'SourceCreator' using a 'Map' 'Key' 'Key' to transform the supplied keys
+-- and another 'SourceCreator'
+mkMappingSource :: Map Key Key -> SourceCreator -> SourceCreator
+mkMappingSource configMap configSource =
+  mkMappingSource' (`Map.lookup` configMap) configSource
diff --git a/src/Conferer/Source/Namespaced.hs b/src/Conferer/Source/Namespaced.hs
new file mode 100644
--- /dev/null
+++ b/src/Conferer/Source/Namespaced.hs
@@ -0,0 +1,23 @@
+module Conferer.Source.Namespaced
+  (
+    -- * Namespaced higher-order source
+    -- | This source takes a source and returns a new source that
+    -- always checks that the 'Key' given always starts with certain 'Key'
+    -- and then strips that prefix before consulting its inner Source
+    mkNamespacedSource
+  ) where
+
+import           Data.List (stripPrefix)
+
+import           Conferer.Types
+
+-- | Create a 'SourceCreator' from a prefix and another 'SourceCreator'
+mkNamespacedSource :: Key -> SourceCreator -> SourceCreator
+mkNamespacedSource (Path key) configCreator = \config -> do
+  configSource <- configCreator config
+  return $ Source
+    { getKeyInSource = \(Path k) -> do
+        case stripPrefix key k of
+          Just newKey -> getKeyInSource configSource (Path newKey)
+          Nothing -> return Nothing
+    }
diff --git a/src/Conferer/Source/Null.hs b/src/Conferer/Source/Null.hs
new file mode 100644
--- /dev/null
+++ b/src/Conferer/Source/Null.hs
@@ -0,0 +1,18 @@
+module Conferer.Source.Null
+  (
+    -- * Does Nothing Source
+    -- | The stub source that never has a key
+    mkNullSource
+  )
+where
+
+import           Conferer.Types
+
+-- | Create a null 'Source'
+mkNullSource :: SourceCreator
+mkNullSource _config =
+  return $ Source
+  { getKeyInSource =
+      \_k -> do
+        return Nothing
+  }
diff --git a/src/Conferer/Source/PropertiesFile.hs b/src/Conferer/Source/PropertiesFile.hs
new file mode 100644
--- /dev/null
+++ b/src/Conferer/Source/PropertiesFile.hs
@@ -0,0 +1,54 @@
+module Conferer.Source.PropertiesFile where
+
+import           Data.Text (Text)
+import           Data.Function ((&))
+import           System.Directory (doesFileExist)
+import           Data.Maybe (catMaybes)
+import qualified Data.Text as Text
+import qualified Data.Text.IO as Text
+
+import           Conferer.Types
+import           Conferer.Source.Files
+import           Conferer.Source.Null
+import           Conferer.Source.Simple
+
+-- | 'SourceCreator' for properties file 'Source' that read from a
+-- config file in @config/{env}.properties@ and parses it as a properties
+-- file with @some.key=a value@ lines
+mkPropertiesFileSource :: SourceCreator
+mkPropertiesFileSource = \config -> do
+  filePath <- getFilePathFromEnv config "properties"
+  fileExists <- doesFileExist filePath
+  if fileExists
+    then do
+      fileContent <- Text.readFile filePath
+      mkPropertiesFileSource' fileContent config
+    else do
+      mkNullSource config
+
+
+-- | 'SourceCreator' for properties file 'Source' that only parses a
+-- given 'Text' as a properties file
+mkPropertiesFileSource' :: Text -> SourceCreator
+mkPropertiesFileSource' fileContent =
+  \config -> do
+    let keyValues =
+          fileContent
+          & Text.lines
+          & fmap lineToKeyValue
+          & catMaybes
+    mkMapSource keyValues config
+
+
+-- | Transform a line into a key/value pair (or not)
+lineToKeyValue :: Text -> Maybe (Key, Text)
+lineToKeyValue line =
+  Text.breakOn "=" line
+  & (\(rawKey, rawValue) ->
+      case Text.stripPrefix "=" rawValue of
+        Just value ->
+          Just (Path $ Text.splitOn "." rawKey, value)
+        Nothing ->
+          Nothing
+    )
+
diff --git a/src/Conferer/Source/Simple.hs b/src/Conferer/Source/Simple.hs
new file mode 100644
--- /dev/null
+++ b/src/Conferer/Source/Simple.hs
@@ -0,0 +1,34 @@
+module Conferer.Source.Simple
+  (
+    -- * Simple Source
+    -- | This source provides values from a hardcoded Map passed at creation
+    -- time that can not be changed afterwards, it's mostly used as a necessary
+    -- utility
+    mkMapSource
+  , mkMapSource'
+  , mkPureMapSource
+  ) where
+
+import           Data.Map (Map)
+import qualified Data.Map as Map
+import           Data.Text (Text)
+
+import           Conferer.Types
+
+-- | Make a 'SourceCreator' from a 'Map'
+mkMapSource' :: Map Key Text -> SourceCreator
+mkMapSource' configMap _config =
+  return $ mkPureMapSource configMap
+
+-- | Make a 'Source' from a 'Map'
+mkPureMapSource :: Map Key Text -> Source
+mkPureMapSource configMap =
+  Source
+    { getKeyInSource =
+      \k -> do
+        return $ Map.lookup k configMap
+    }
+
+-- | Make a 'Source' from 'List' of 'Key', 'Text' pairs
+mkMapSource :: [(Key, Text)] -> SourceCreator
+mkMapSource = mkMapSource' . Map.fromList
diff --git a/src/Conferer/Types.hs b/src/Conferer/Types.hs
--- a/src/Conferer/Types.hs
+++ b/src/Conferer/Types.hs
@@ -17,14 +17,14 @@
 
 -- | Core interface for library provided configuration, basically consists of
 --   getting a 'Key' and informing returning a maybe signaling the value and
---   if it's present in that specific provider
-data Provider =
-  Provider
-  { getKeyInProvider :: Key -> IO (Maybe Text)
+--   if it's present in that specific source
+data Source =
+  Source
+  { getKeyInSource :: Key -> IO (Maybe Text)
   }
 
--- | The way to index 'Provider's, basically list of names that will be adapted
---   to whatever the provider needs
+-- | The way to index 'Source's, basically list of names that will be adapted
+--   to whatever the source needs
 newtype Key
   = Path { unKey :: [Text] }
   deriving (Show, Eq, Ord)
@@ -37,17 +37,17 @@
 keyName = Text.intercalate "." . unKey
 
 -- | Core type that the user of this library interact with, in the future it may
---   contain more this besides a list of providers
+--   contain more this besides a list of sources
 data Config =
   Config
-  { providers :: [Provider]
+  { sources :: [Source]
   , defaults :: Map Key Text
   }
 
--- | The type for creating a provider given a 'Config', some providers require a
--- certain configuration to be initialized (for example: the redis provider
+-- | The type for creating a source given a 'Config', some sources require a
+-- certain configuration to be initialized (for example: the redis source
 -- needs connection info to connect to the server)
-type ProviderCreator = Config -> IO Provider
+type SourceCreator = Config -> IO Source
 
 keyNotPresentError :: forall a. (Typeable a) => Key -> Proxy a -> FailedToFetchError
 keyNotPresentError key =
@@ -62,7 +62,7 @@
   configDef :: a
 
 -- | Main typeclass for defining the way to get values from config, hiding the
--- 'Text' based nature of the 'Provider's.
+-- 'Text' based nature of the 'Source's.
 -- updated using a config, so for example a Warp.Settings can get updated from a config,
 -- but that doesn't make much sense for something like an 'Int'
 --
diff --git a/test/Conferer/FromConfig/BasicsSpec.hs b/test/Conferer/FromConfig/BasicsSpec.hs
--- a/test/Conferer/FromConfig/BasicsSpec.hs
+++ b/test/Conferer/FromConfig/BasicsSpec.hs
@@ -13,7 +13,7 @@
 import           Control.DeepSeq
 
 configWith :: [(Key, Text)] -> IO Config
-configWith keyValues = emptyConfig & addProvider (mkMapProvider keyValues)
+configWith keyValues = emptyConfig & addSource (mkMapSource keyValues)
 
 configParserError_ :: ConfigParsingError -> Bool
 configParserError_ = const True
diff --git a/test/Conferer/GenericsSpec.hs b/test/Conferer/GenericsSpec.hs
--- a/test/Conferer/GenericsSpec.hs
+++ b/test/Conferer/GenericsSpec.hs
@@ -38,14 +38,14 @@
       context "when no keys are set" $ do
         it "returns the default" $ do
           c <- emptyConfig
-                & addProvider (mkMapProvider [ ])
+                & addSource (mkMapSource [ ])
 
           res <- fetch @Thing "somekey" c
           res `shouldBe` Thing { thingA = 0, thingB = 0 }
       context "when all keys are set" $ do
         it "return the keys set" $ do
           c <- emptyConfig
-                & addProvider (mkMapProvider
+                & addSource (mkMapSource
                   [ ("somekey.a", "1")
                   , ("somekey.b", "2")
                   ])
@@ -56,7 +56,7 @@
       context "when some keys are set" $ do
         it "uses the default and returns the keys set" $ do
           c <- emptyConfig
-                & addProvider (mkMapProvider
+                & addSource (mkMapSource
                   [ ("somekey.b", "2")
                   ])
 
@@ -67,7 +67,7 @@
       context "when none of the keys are set" $ do
         it "returns the default of both records" $ do
           c <- emptyConfig
-                & addProvider (mkMapProvider
+                & addSource (mkMapSource
                   [ ])
 
           res <- fetch @Bigger "somekey" c
@@ -76,7 +76,7 @@
       context "when some keys of the top record are set" $ do
         it "returns the default for the inner record" $ do
           c <- emptyConfig
-                & addProvider (mkMapProvider
+                & addSource (mkMapSource
                   [ ("somekey.b", "30")
                   ])
 
@@ -86,7 +86,7 @@
       context "when some keys of the inner record are set" $ do
         it "returns the inner record updated" $ do
           c <- emptyConfig
-                & addProvider (mkMapProvider
+                & addSource (mkMapSource
                   [ ("somekey.thing.a", "30")
                   ])
 
@@ -96,7 +96,7 @@
       context "when every key is set" $ do
         it "returns everything with the right values" $ do
           c <- emptyConfig
-                & addProvider (mkMapProvider
+                & addSource (mkMapSource
                   [ ("somekey.thing.a", "10")
                   , ("somekey.thing.b", "20")
                   , ("somekey.b", "30")
diff --git a/test/Conferer/Provider/ArgsSpec.hs b/test/Conferer/Provider/ArgsSpec.hs
deleted file mode 100644
--- a/test/Conferer/Provider/ArgsSpec.hs
+++ /dev/null
@@ -1,38 +0,0 @@
-module Conferer.Provider.ArgsSpec where
-
-import           Test.Hspec
-
-import           Conferer
-
-spec :: Spec
-spec = do
-  describe "with a mapping provider" $ do
-    let mkConf args =
-          emptyConfig
-          & addProvider
-          (mkCLIArgsProvider' args)
-
-    it "gets a parameters with it's value if it starts with the right prefix" $ do
-      c <- mkConf []
-      res <- getKey "some.key" c
-      res `shouldBe` Nothing
-
-    it "with a value that begins with the right prefix it uses it" $ do
-      c <- mkConf ["--some.key=value"]
-      res <- getKey "some.key" c
-      res `shouldBe` Just "value"
-
-    it "with a reapeated value it uses the last one" $ do
-      c <- mkConf ["--some.key=value", "--some.key=different value"]
-      res <- getKey "some.key" c
-      res `shouldBe` Just "different value"
-
-    it "ignores values that don't start with the right prefix" $ do
-      c <- mkConf ["some.key=value", "-some.key=value", "-Xsome.key=value", "some.key"]
-      res <- getKey "some.key" c
-      res `shouldBe` Nothing
-
-    it "after encountering a -- it stops parsing parameters" $ do
-      c <- mkConf ["--", "--some.key=value"]
-      res <- getKey "some.key" c
-      res `shouldBe` Nothing
diff --git a/test/Conferer/Provider/EnvSpec.hs b/test/Conferer/Provider/EnvSpec.hs
deleted file mode 100644
--- a/test/Conferer/Provider/EnvSpec.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-module Conferer.Provider.EnvSpec where
-
-import           Test.Hspec
-import qualified Data.Map as Map
-
-import Conferer
-
-fakeLookupEnv :: [(String, String)] -> LookupEnvFunc
-fakeLookupEnv fakeEnv = \envName ->
-  return $ Map.lookup envName $ Map.fromList fakeEnv
-
-spec :: Spec
-spec = do
-  describe "with an env config" $ do
-    let
-      mkEnvConfig =
-        emptyConfig
-        & addProvider
-        (mkEnvProvider'
-         (fakeLookupEnv
-          [ ("TMUX","/tmp/tmux-1000/default,2822,0")
-          , ("TMUX_PANE","%1")
-          , ("TMUX_PLUGIN_MANAGER_PATH","/home/user/.tmux/plugins/")
-          ])
-         "TMUX"
-        )
-    it "getting an existent key returns unwraps top level value (wihtout \
-       \children)" $ do
-      c <- mkEnvConfig
-      res <- getKey "." c
-      res `shouldBe` Just "/tmp/tmux-1000/default,2822,0"
-
-    it "getting an existent key for a child gets that value" $ do
-      c <- mkEnvConfig
-      res <- getKey "pane" c
-      res `shouldBe` Just "%1"
-
-    it "keys should always be consistent as to how the words are separated" $ do
-      c <- mkEnvConfig
-      res <- getKey "pane" c
-      res `shouldBe` Just "%1"
diff --git a/test/Conferer/Provider/MappingSpec.hs b/test/Conferer/Provider/MappingSpec.hs
deleted file mode 100644
--- a/test/Conferer/Provider/MappingSpec.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-module Conferer.Provider.MappingSpec where
-
-import           Test.Hspec
-import qualified Data.Map as Map
-import           Data.Function ((&))
-
-import           Conferer
-
-spec :: Spec
-spec = do
-  describe "with a mapping provider" $ do
-    it "getting an existent key in the original map but that's not mapped in the \
-       \wrapper doesn't exist" $ do
-      c <- emptyConfig
-           & addProvider (mkMappingProvider Map.empty
-                          $ mkMapProvider [("some.key", "some value")])
-      res <- getKey "some.key" c
-      res `shouldBe` Nothing
-
-    it "getting a non existent key isn't there" $ do
-      c <- emptyConfig
-           & addProvider (mkMappingProvider (Map.fromList [("k", "key")])
-                          $ mkMapProvider [("key", "75")])
-
-      res <- getKey "xxxx" c
-      res `shouldBe` Nothing
-
-    it "getting an existent key that's mapped but doesn't exist on the \
-       \inner provider isn't there" $ do
-      c <- emptyConfig
-           & addProvider (mkMappingProvider (Map.fromList [("another.key", "some.key")])
-                          $ mkMapProvider [])
-
-      res <- getKey "another.key" c
-      res `shouldBe` Nothing
-
-    it "getting an existent key that's mapped properly gets it and exists on \
-       \the inner provider gets it" $ do
-      c <- emptyConfig
-           & addProvider (mkMappingProvider (Map.fromList [("another.key", "some.key")])
-                          $ mkMapProvider [("some.key", "some value")])
-      res <- getKey "another.key" c
-      res `shouldBe` Just "some value"
diff --git a/test/Conferer/Provider/NamespacedSpec.hs b/test/Conferer/Provider/NamespacedSpec.hs
deleted file mode 100644
--- a/test/Conferer/Provider/NamespacedSpec.hs
+++ /dev/null
@@ -1,21 +0,0 @@
-module Conferer.Provider.NamespacedSpec where
-
-import Test.Hspec
-
-import Conferer
-
-spec :: Spec
-spec = do
-  describe "namespaced config" $ do
-    it "return nothing if the key doesn't match" $ do
-      c <- emptyConfig
-           & addProvider (mkNamespacedProvider "postgres"
-                          $ mkMapProvider [("url", "some url")])
-      res <- getKey "url" c
-      res `shouldBe` Nothing
-    it "returns the wrapped value" $ do
-      c <- emptyConfig
-           & addProvider (mkNamespacedProvider "postgres"
-                          $ mkMapProvider [("url", "some url")])
-      res <- getKey "postgres.url" c
-      res `shouldBe` Just "some url"
diff --git a/test/Conferer/Provider/NullSpec.hs b/test/Conferer/Provider/NullSpec.hs
deleted file mode 100644
--- a/test/Conferer/Provider/NullSpec.hs
+++ /dev/null
@@ -1,13 +0,0 @@
-module Conferer.Provider.NullSpec where
-
-import           Test.Hspec
-
-import           Conferer
-
-spec :: Spec
-spec = do
-  it "always fails to get a key" $ do
-    c <- emptyConfig
-         & addProvider mkNullProvider
-    res <- getKey "some.key" c
-    res `shouldBe` Nothing
diff --git a/test/Conferer/Provider/PropertiesFileSpec.hs b/test/Conferer/Provider/PropertiesFileSpec.hs
deleted file mode 100644
--- a/test/Conferer/Provider/PropertiesFileSpec.hs
+++ /dev/null
@@ -1,39 +0,0 @@
-module Conferer.Provider.PropertiesFileSpec where
-
-import           Test.Hspec
-import           Data.Text (Text)
-import qualified Data.Text as Text
-import qualified Data.Map as Map
-
-import Conferer
-import Conferer.Core
-import Conferer.Provider.PropertiesFile
-
-fakeLookupEnv :: [(String, String)] -> LookupEnvFunc
-fakeLookupEnv fakeEnv = \envName ->
-  return $ Map.lookup envName $ Map.fromList fakeEnv
-
-spec :: Spec
-spec = do
-  describe "with a properties file config" $ do
-    it "getting an existent key returns unwraps top level value (wihtout \
-       \children)" $ do
-      c <- mkStandaloneProvider $ mkPropertiesFileProvider' "some.key=a value"
-      res <- getKeyInProvider c "some.key"
-      res `shouldBe` Just "a value"
-
-    it "getting an existent key for a child gets that value" $ do
-      c <- mkStandaloneProvider $ mkPropertiesFileProvider' $ Text.unlines
-                               [ "some.key=a value"
-                               , "some.key=b"
-                               ]
-      res <- getKeyInProvider c "some.key"
-      res `shouldBe` Just "b"
-
-    it "keys should always be consistent as to how the words are separated" $ do
-      c <- mkStandaloneProvider $ mkPropertiesFileProvider' $ Text.unlines
-                               [ "some.key=a value"
-                               , "some.key=b"
-                               ]
-      res <- getKeyInProvider c "another.key"
-      res `shouldBe` Nothing
diff --git a/test/Conferer/Provider/SimpleSpec.hs b/test/Conferer/Provider/SimpleSpec.hs
deleted file mode 100644
--- a/test/Conferer/Provider/SimpleSpec.hs
+++ /dev/null
@@ -1,22 +0,0 @@
-module Conferer.Provider.SimpleSpec where
-
-import Test.Hspec
-
-import Conferer
-
-spec :: Spec
-spec = do
-  describe "json provider" $ do
-    let creator =
-          emptyConfig
-          & addProvider (mkMapProvider [ ("postgres.url", "some url")])
-
-    it "getting a non existent key returns an empty config" $ do
-      c <- creator
-      res <- getKey "some.key" c
-      res `shouldBe` Nothing
-
-    it "getting an existent key returns unwraps the original map" $ do
-      c <- creator
-      res <- getKey "postgres.url" c
-      res `shouldBe` Just "some url"
diff --git a/test/Conferer/Source/ArgsSpec.hs b/test/Conferer/Source/ArgsSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Conferer/Source/ArgsSpec.hs
@@ -0,0 +1,38 @@
+module Conferer.Source.ArgsSpec where
+
+import           Test.Hspec
+
+import           Conferer
+
+spec :: Spec
+spec = do
+  describe "with a mapping source" $ do
+    let mkConf args =
+          emptyConfig
+          & addSource
+          (mkCLIArgsSource' args)
+
+    it "gets a parameters with it's value if it starts with the right prefix" $ do
+      c <- mkConf []
+      res <- getKey "some.key" c
+      res `shouldBe` Nothing
+
+    it "with a value that begins with the right prefix it uses it" $ do
+      c <- mkConf ["--some.key=value"]
+      res <- getKey "some.key" c
+      res `shouldBe` Just "value"
+
+    it "with a reapeated value it uses the last one" $ do
+      c <- mkConf ["--some.key=value", "--some.key=different value"]
+      res <- getKey "some.key" c
+      res `shouldBe` Just "different value"
+
+    it "ignores values that don't start with the right prefix" $ do
+      c <- mkConf ["some.key=value", "-some.key=value", "-Xsome.key=value", "some.key"]
+      res <- getKey "some.key" c
+      res `shouldBe` Nothing
+
+    it "after encountering a -- it stops parsing parameters" $ do
+      c <- mkConf ["--", "--some.key=value"]
+      res <- getKey "some.key" c
+      res `shouldBe` Nothing
diff --git a/test/Conferer/Source/EnvSpec.hs b/test/Conferer/Source/EnvSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Conferer/Source/EnvSpec.hs
@@ -0,0 +1,41 @@
+module Conferer.Source.EnvSpec where
+
+import           Test.Hspec
+import qualified Data.Map as Map
+
+import Conferer
+
+fakeLookupEnv :: [(String, String)] -> LookupEnvFunc
+fakeLookupEnv fakeEnv = \envName ->
+  return $ Map.lookup envName $ Map.fromList fakeEnv
+
+spec :: Spec
+spec = do
+  describe "with an env config" $ do
+    let
+      mkEnvConfig =
+        emptyConfig
+        & addSource
+        (mkEnvSource'
+         (fakeLookupEnv
+          [ ("TMUX","/tmp/tmux-1000/default,2822,0")
+          , ("TMUX_PANE","%1")
+          , ("TMUX_PLUGIN_MANAGER_PATH","/home/user/.tmux/plugins/")
+          ])
+         "TMUX"
+        )
+    it "getting an existent key returns unwraps top level value (wihtout \
+       \children)" $ do
+      c <- mkEnvConfig
+      res <- getKey "." c
+      res `shouldBe` Just "/tmp/tmux-1000/default,2822,0"
+
+    it "getting an existent key for a child gets that value" $ do
+      c <- mkEnvConfig
+      res <- getKey "pane" c
+      res `shouldBe` Just "%1"
+
+    it "keys should always be consistent as to how the words are separated" $ do
+      c <- mkEnvConfig
+      res <- getKey "pane" c
+      res `shouldBe` Just "%1"
diff --git a/test/Conferer/Source/MappingSpec.hs b/test/Conferer/Source/MappingSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Conferer/Source/MappingSpec.hs
@@ -0,0 +1,43 @@
+module Conferer.Source.MappingSpec where
+
+import           Test.Hspec
+import qualified Data.Map as Map
+import           Data.Function ((&))
+
+import           Conferer
+
+spec :: Spec
+spec = do
+  describe "with a mapping source" $ do
+    it "getting an existent key in the original map but that's not mapped in the \
+       \wrapper doesn't exist" $ do
+      c <- emptyConfig
+           & addSource (mkMappingSource Map.empty
+                          $ mkMapSource [("some.key", "some value")])
+      res <- getKey "some.key" c
+      res `shouldBe` Nothing
+
+    it "getting a non existent key isn't there" $ do
+      c <- emptyConfig
+           & addSource (mkMappingSource (Map.fromList [("k", "key")])
+                          $ mkMapSource [("key", "75")])
+
+      res <- getKey "xxxx" c
+      res `shouldBe` Nothing
+
+    it "getting an existent key that's mapped but doesn't exist on the \
+       \inner source isn't there" $ do
+      c <- emptyConfig
+           & addSource (mkMappingSource (Map.fromList [("another.key", "some.key")])
+                          $ mkMapSource [])
+
+      res <- getKey "another.key" c
+      res `shouldBe` Nothing
+
+    it "getting an existent key that's mapped properly gets it and exists on \
+       \the inner source gets it" $ do
+      c <- emptyConfig
+           & addSource (mkMappingSource (Map.fromList [("another.key", "some.key")])
+                          $ mkMapSource [("some.key", "some value")])
+      res <- getKey "another.key" c
+      res `shouldBe` Just "some value"
diff --git a/test/Conferer/Source/NamespacedSpec.hs b/test/Conferer/Source/NamespacedSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Conferer/Source/NamespacedSpec.hs
@@ -0,0 +1,21 @@
+module Conferer.Source.NamespacedSpec where
+
+import Test.Hspec
+
+import Conferer
+
+spec :: Spec
+spec = do
+  describe "namespaced config" $ do
+    it "return nothing if the key doesn't match" $ do
+      c <- emptyConfig
+           & addSource (mkNamespacedSource "postgres"
+                          $ mkMapSource [("url", "some url")])
+      res <- getKey "url" c
+      res `shouldBe` Nothing
+    it "returns the wrapped value" $ do
+      c <- emptyConfig
+           & addSource (mkNamespacedSource "postgres"
+                          $ mkMapSource [("url", "some url")])
+      res <- getKey "postgres.url" c
+      res `shouldBe` Just "some url"
diff --git a/test/Conferer/Source/NullSpec.hs b/test/Conferer/Source/NullSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Conferer/Source/NullSpec.hs
@@ -0,0 +1,13 @@
+module Conferer.Source.NullSpec where
+
+import           Test.Hspec
+
+import           Conferer
+
+spec :: Spec
+spec = do
+  it "always fails to get a key" $ do
+    c <- emptyConfig
+         & addSource mkNullSource
+    res <- getKey "some.key" c
+    res `shouldBe` Nothing
diff --git a/test/Conferer/Source/PropertiesFileSpec.hs b/test/Conferer/Source/PropertiesFileSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Conferer/Source/PropertiesFileSpec.hs
@@ -0,0 +1,39 @@
+module Conferer.Source.PropertiesFileSpec where
+
+import           Test.Hspec
+import           Data.Text (Text)
+import qualified Data.Text as Text
+import qualified Data.Map as Map
+
+import Conferer
+import Conferer.Core
+import Conferer.Source.PropertiesFile
+
+fakeLookupEnv :: [(String, String)] -> LookupEnvFunc
+fakeLookupEnv fakeEnv = \envName ->
+  return $ Map.lookup envName $ Map.fromList fakeEnv
+
+spec :: Spec
+spec = do
+  describe "with a properties file config" $ do
+    it "getting an existent key returns unwraps top level value (wihtout \
+       \children)" $ do
+      c <- mkStandaloneSource $ mkPropertiesFileSource' "some.key=a value"
+      res <- getKeyInSource c "some.key"
+      res `shouldBe` Just "a value"
+
+    it "getting an existent key for a child gets that value" $ do
+      c <- mkStandaloneSource $ mkPropertiesFileSource' $ Text.unlines
+                               [ "some.key=a value"
+                               , "some.key=b"
+                               ]
+      res <- getKeyInSource c "some.key"
+      res `shouldBe` Just "b"
+
+    it "keys should always be consistent as to how the words are separated" $ do
+      c <- mkStandaloneSource $ mkPropertiesFileSource' $ Text.unlines
+                               [ "some.key=a value"
+                               , "some.key=b"
+                               ]
+      res <- getKeyInSource c "another.key"
+      res `shouldBe` Nothing
diff --git a/test/Conferer/Source/SimpleSpec.hs b/test/Conferer/Source/SimpleSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Conferer/Source/SimpleSpec.hs
@@ -0,0 +1,22 @@
+module Conferer.Source.SimpleSpec where
+
+import Test.Hspec
+
+import Conferer
+
+spec :: Spec
+spec = do
+  describe "json source" $ do
+    let creator =
+          emptyConfig
+          & addSource (mkMapSource [ ("postgres.url", "some url")])
+
+    it "getting a non existent key returns an empty config" $ do
+      c <- creator
+      res <- getKey "some.key" c
+      res `shouldBe` Nothing
+
+    it "getting an existent key returns unwraps the original map" $ do
+      c <- creator
+      res <- getKey "postgres.url" c
+      res `shouldBe` Just "some url"
diff --git a/test/ConfererSpec.hs b/test/ConfererSpec.hs
--- a/test/ConfererSpec.hs
+++ b/test/ConfererSpec.hs
@@ -14,8 +14,8 @@
   describe "with a config with a nested value" $ do
     let mkConfig =
           pure emptyConfig
-          >>= addProvider (mkMapProvider [ ("postgres.url", "some url")])
-          >>= addProvider (mkMapProvider [ ("postgres.url", "different url") , ("server.port", "4000")])
+          >>= addSource (mkMapSource [ ("postgres.url", "some url")])
+          >>= addSource (mkMapSource [ ("postgres.url", "different url") , ("server.port", "4000")])
 
     it "getting a non existent key returns an empty config" $ do
       c <- mkConfig
