diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -24,7 +24,9 @@
 ### What's new:
 - Bonjour! Herm's now has language support for Français (French), English, and Pirate. Set your language preferences in ``config.hs``!
 - These are but the first languages that Herm's is now capable of supporting. We need your help to translate it into others! Currently in progress: Português (Portuguese), Español (Spanish)
+- Herm's now conforms to the [XDG Base Directory Specification](http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html). In short, `config.hs` and `recipes.herms` are now stored in `~/.config/herms` and `~/.local/share/herms` respectively on most Linux systems.
 
+
 ### Installation
 
 At the moment, Herm's can only be installed via [stack](https://docs.haskellstack.org/en/stable/README/) or [cabal](https://www.haskell.org/cabal/), but standalone binaries are in the works!
@@ -95,7 +97,7 @@
 
         herms shopping RECIPE_NAMES [-s|--serving INT] generate shopping list for particular recipes
 
-        herms datadir                                  print location of recipe and config files
+        herms datadir                                  show locations of recipe and config files
 
 Available options:
 
@@ -125,7 +127,15 @@
 
 #### Configuring Herm's and managing recipe files
 
-Herm's stores its recipes file, ``recipes.herms``,  and configuration file, ``config.hs``, in the same directory. Herm's keeps track of its location! Run ``herms datadir`` to see the full directory path.
+Herm's stores files in the following locations:
+
+- The configuration file, `config.hs` in the XDG configuration directory,
+  typically `~/.config/herms` on most Linux systems
+
+- The recipes file, `recipes.herms` in the XDG data directory,
+  typically `~/.local/share/herms` on most Linux systems
+
+To see where these are stored on your system, run ``herms datadir``.
 
 ``config.hs`` is a pseudo-Haskell-source-code file with several options for configuring the behaviour of Herm's. It currently supports the following options:
 
diff --git a/app/herms.hs b/app/herms.hs
--- a/app/herms.hs
+++ b/app/herms.hs
@@ -1,9 +1,10 @@
 {-# LANGUAGE ViewPatterns #-}
 
+
 module Main where
 
-import System.Directory
 import System.IO
+import System.Directory
 import Control.Monad
 import Control.Monad.IO.Class
 import Control.Monad.Reader
@@ -18,12 +19,10 @@
 import Text.Read
 import Utils
 import AddCLI
-import AddFile
 import RichText
 import Types
 import UnitConversions
 import ReadConfig
-import Paths_herms
 import Control.Exception
 import GHC.IO.Exception
 import Foreign.C.Error
@@ -31,19 +30,15 @@
 
 -- Global constants
 versionStr :: String
-versionStr = "1.9.0.3"
-
-configPath :: IO FilePath
-configPath = getDataFileName "config.hs"
+versionStr = "1.9.0.4"
 
 type HermsReader = ReaderT (Config, RecipeBook)
 
 -- | @getRecipeBookWith reads in recipe book with already read-in config
 getRecipeBookWith :: Config -> IO [Recipe]
-getRecipeBookWith config = do
-  fileName <- getDataFileName (recipesFile' config)
-  contents <- readFile fileName
-  return $ map read $ lines contents
+getRecipeBookWith config =
+  fmap (map read . lines) $
+    readFileOrDefault "recipes.herms" (recipesFile' config)
 
 getRecipe :: String -> [Recipe] -> Maybe Recipe
 getRecipe target = listToMaybe . filter ((target ==) . recipeName)
@@ -57,44 +52,33 @@
   let newRecipe = readRecipe input
   liftIO $ putTextLn $ showRecipe t newRecipe Nothing
   liftIO $ putStrLn (t Str.saveRecipeYesNoEdit)
-  response <- liftIO $ getLine
-  if response == (t Str.y) || response == (t Str.yCap)
+  response <- liftIO getLine
+  if response == t Str.y || response == t Str.yCap
     then do
     let recpName = maybe (recipeName newRecipe) recipeName oldRecp
     unless (isNothing (readRecipeRef recpName recipeBook)) $ removeSilent [recpName]
-    fileName <- liftIO $ getDataFileName (recipesFile' config)
-    liftIO $ appendFile fileName (show newRecipe ++ "\n")
+    liftIO $ appendFile (recipesFile' config) (show newRecipe ++ "\n")
     liftIO $ putStrLn (t Str.recipeSaved)
-  else if response == (t Str.n) || response == (t Str.nCap)
+  else if response == t Str.n || response == t Str.nCap
     then
     liftIO $ putStrLn (t Str.changesDiscarded)
-  else if response == (t Str.e) || response == (t Str.eCap)
+  else if response == t Str.e || response == t Str.eCap
     then
     doEdit newRecipe oldRecp
   else
     do
-    liftIO $ putStrLn ("\n" ++ (t Str.badEntry) ++ "\n")
+    liftIO $ putStrLn ("\n" ++ t Str.badEntry ++ "\n")
     saveOrDiscard input oldRecp
 
-addInteractive :: HermsReader IO ()
-addInteractive = do
-  (config, recipeBook) <- ask
+add :: HermsReader IO ()
+add = do
+  (config, _) <- ask
   input <- liftIO $ getAddInput (translator config)
   saveOrDiscard input Nothing
 
-
-add :: [String] -> HermsReader IO ()
-add []        = addInteractive
-add filenames = do
-  (config, recipeBook) <- ask
-  forM_ filenames $ \ filename -> do
-    contents <- liftIO $ readFile filename
-    saveOrDiscard (readRecipeFileData contents) Nothing
-  
-
 doEdit :: Recipe -> Maybe Recipe -> HermsReader IO ()
 doEdit recp origRecp = do
-  (config, recipeBook) <- ask
+  (config, _) <- ask
   input <- liftIO $ getEdit (translator config) (recipeName recp) (description recp) serving amounts units ingrs attrs dirs tag
   saveOrDiscard input origRecp
   where serving  = show $ servingSize recp
@@ -112,7 +96,7 @@
   (config, recipeBook) <- ask
   let t = translator config
   case readRecipeRef target recipeBook of
-    Nothing   -> liftIO $ putStrLn $ target ++ (t Str.doesNotExist)
+    Nothing   -> liftIO $ putStrLn $ target ++ t Str.doesNotExist
     Just recp -> doEdit recp (Just recp)
   -- Only supports editing one recipe per command
 
@@ -146,7 +130,7 @@
   let t = translator config
   liftIO $ forM_ targets $ \ target ->
     putText $ case readRecipeRef target recipeBook of
-      Nothing   -> target ~~ (t Str.doesNotExist)
+      Nothing   -> target ~~ t Str.doesNotExist
       Just recp -> fromString $ show recp
 
 getServingsAndConv :: Int -> String -> Config -> (Maybe Int, Conversion)
@@ -158,18 +142,18 @@
                    i -> Just i
         t = translator config
         conv
-          | convName  == (t Str.metric)   =  Metric
-          | convName  == (t Str.imperial) =  Imperial
+          | convName  == t Str.metric   =  Metric
+          | convName  == t Str.imperial =  Imperial
           | otherwise = defaultUnit' config
 
 view :: [String] -> Int -> String -> HermsReader IO ()
 view targets serv convName = do
-  (config,recipeBook) <- ask
+  (config, recipeBook) <- ask
   let t = translator config
   let (servings, conv) = getServingsAndConv serv convName config
   liftIO $ forM_ targets $ \ target ->
     putText $ case readRecipeRef target recipeBook of
-      Nothing   -> target ~~ (t Str.doesNotExist)
+      Nothing   -> target ~~ t Str.doesNotExist
       Just recp -> showRecipe t (convertRecipeUnits conv recp) servings
 
 viewByStep :: [String] -> Int -> String -> HermsReader IO ()
@@ -179,23 +163,23 @@
   let (servings, conv) = getServingsAndConv serv convName config
   liftIO $ hSetBuffering stdout NoBuffering
   forM_ targets $ \ target -> case readRecipeRef target recipeBook of
-    Nothing   -> liftIO $ putStr $ target ++ (t Str.doesNotExist)
+    Nothing   -> liftIO $ putStr $ target ++ t Str.doesNotExist
     Just recp -> viewRecipeByStep (convertRecipeUnits conv recp) servings
 
 viewRecipeByStep :: Recipe -> Maybe Int -> HermsReader IO ()
 viewRecipeByStep recp servings = do
-  (config, recipeBook) <- ask
+  (config, _) <- ask
   let t = translator config
   liftIO $ putText $ showRecipeHeader t recp servings
   let steps = showRecipeSteps recp
   liftIO $ forM_ (init steps) $ \ step -> do
-    putStr $ step ++ (t Str.more)
+    putStr $ step ++ t Str.more
     getLine
   liftIO $ putStr $ last steps ++ "\n"
 
 list :: [String] -> Bool -> Bool -> HermsReader IO ()
 list inputTags groupByTags nameOnly = do
-  (config,recipes) <- ask
+  (_, recipes) <- ask
   let recipesWithIndex = zip [1..] recipes
   let targetRecipes    = filterByTags inputTags recipesWithIndex
   if groupByTags
@@ -210,7 +194,7 @@
 
 listDefault :: Bool -> [(Int, Recipe)] -> HermsReader IO ()
 listDefault nameOnly (unzip -> (indices, recipes)) = do
-  (config, recipeBook) <- ask
+  (config, _) <- ask
   let recipeList = map (showRecipeInfo (translator config)) recipes
       size       = length $ show $ length recipeList
       strIndices = map (padLeft size . show) indices
@@ -220,7 +204,7 @@
 
 listByTags :: Bool -> [String] -> [(Int, Recipe)] -> HermsReader IO ()
 listByTags nameOnly inputTags recipesWithIdx = do
-  (config, recipeBook) <- ask
+  (config, _) <- ask
   let tagsRecipes :: [[(String, (Int, Recipe))]]
       tagsRecipes =
         groupBy ((==) `on` fst) $ sortBy (compare `on` fst) $
@@ -239,7 +223,7 @@
   where name     = fontColor Blue $ recipeName recipe
         desc     = (takeFullWords . description) recipe
         showTags = fontColor Green $ (intercalate ", " . tags) recipe
-        tagsStr  = fontColor White $ (t Str.capTags)
+        tagsStr  = fontColor White (t Str.capTags)
 
 takeFullWords :: String -> String
 takeFullWords = unwords . takeFullWords' 0 . words
@@ -256,11 +240,10 @@
 --   and finally moves the temporary file over to the target @fp@.
 
 replaceDataFile :: FilePath -> String -> IO ()
-replaceDataFile fp str = do
+replaceDataFile fileName str = do
   (tempName, tempHandle) <- openTempFile "." "herms_temp"
   hPutStr tempHandle str
   hClose tempHandle
-  fileName <- getDataFileName fp
   removeFile fileName
   let exdev e = if ioe_errno e == Just ((\(Errno a) -> a) eXDEV)
                     then copyFile tempName fileName >> removeFile tempName
@@ -282,8 +265,8 @@
     -- remove anything
     let mrecp = readRecipeRef target recipeBook
     () <- putStr $ case mrecp of
-       Nothing -> target ++ (t Str.doesNotExist)
-       Just r  -> guard v *> (t Str.removingRecipe) ++ recipeName r ++ "...\n"
+       Nothing -> target ++ t Str.doesNotExist
+       Just r  -> guard v *> t Str.removingRecipe ++ recipeName r ++ "...\n"
     return mrecp
   -- Remove all the resolved recipes at once
   let newRecipeBook = recipeBook \\ catMaybes mrecipes
@@ -297,7 +280,7 @@
 
 shop :: [String] -> Int -> HermsReader IO ()
 shop targets serv = do
-  (config, recipeBook) <- ask
+  (_, recipeBook) <- ask
   let getFactor recp
         | serv == 0 = servingSize recp % 1
         | otherwise = serv % 1
@@ -312,19 +295,9 @@
 
 printDataDir :: HermsReader IO ()
 printDataDir = do
-  dir <- liftIO $ getDataDir
-  liftIO $ putStrLn $ filter (/= '\"') (show dir) ++ "/"
-
--- Writes an empty recipes file if it doesn't exist
-checkFileExists :: IO ()
-checkFileExists = do
-  config   <- getConfig
-  fileName <- getDataFileName (recipesFile' config)
-  fileExists <- doesFileExist fileName
-  unless fileExists (do
-    dirName <- getDataDir
-    createDirectoryIfMissing True dirName
-    writeFile fileName "")
+  (config, _) <- ask
+  liftIO $ mapM_ (putStrLn . cleanDirPath) [dataDir config, configDir config]
+  where cleanDirPath = (++ "/") . filter (/= '\"')
 
 main :: IO ()
 main = do
@@ -336,14 +309,14 @@
 -- @runWithOpts runs the action of selected command.
 runWithOpts :: Command -> HermsReader IO ()
 runWithOpts (List tags group nameOnly)              = list tags group nameOnly
-runWithOpts (Add targets)                           = add targets
+runWithOpts Add                                     = add
 runWithOpts (Edit target)                           = edit target
 runWithOpts (Import target)                         = importFile target
 runWithOpts (Export targets)                        = export targets
 runWithOpts (Remove targets)                        = remove targets
-runWithOpts (View targets serving step conversion)  = if step 
+runWithOpts (View targets serving step conversion)  = if step
                                                       then viewByStep targets serving conversion
-                                                      else view targets serving conversion 
+                                                      else view targets serving conversion
 runWithOpts (Shop targets serving)                  = shop targets serving
 runWithOpts DataDir                                 = printDataDir
 
@@ -355,26 +328,25 @@
 -- | 'Command' data type represents commands of CLI
 data Command = List   [String] Bool Bool         -- ^ shows recipes
              | View   [String] Int Bool String   -- ^ shows specified recipes with given serving
-             | Add    [String]                   -- ^ adds the recipe (interactively or from files)
+             | Add                               -- ^ adds the recipe (interactively)
              | Edit    String                    -- ^ edits the recipe
              | Import  String                    -- ^ imports a recipe file
              | Export  [String]                  -- ^ exports recipes to stdout
              | Remove [String]                   -- ^ removes specified recipes
              | Shop   [String] Int               -- ^ generates the shopping list for given recipes
-             | DataDir                           -- ^ prints the directory of recipe file and config.hs
+             | DataDir                           -- ^ prints the directories of recipe file and config.hs
 
-listP, addP, viewP, editP, importP, exportP, shopP, dataDirP :: Translator -> Parser Command
-listP    t = List   <$> (words <$> (tagsP t)) <*> (groupByTagsP t) <*> (nameOnlyP t)
-addP     t = Add    <$> (severalFilesP t)
-editP    t = Edit   <$> (recipeNameP t)
-importP  t = Import <$> (fileNameP t)
-exportP  t = Export <$> (severalRecipesP t)
-removeP  t = Remove <$> (severalRecipesP t)
-viewP    t = View   <$> (severalRecipesP t) <*> (servingP t) <*> (stepP t) <*> (conversionP t)
-shopP    t = Shop   <$> (severalRecipesP t) <*> (servingP t)
+listP, addP, viewP, editP, importP, exportP, removeP, shopP, dataDirP :: Translator -> Parser Command
+listP    t = List   <$> (words <$> tagsP t) <*> groupByTagsP t <*> nameOnlyP t
+addP     _ = pure Add
+editP    t = Edit   <$> recipeNameP t
+importP  t = Import <$> fileNameP t
+exportP  t = Export <$> severalRecipesP t
+removeP  t = Remove <$> severalRecipesP t
+viewP    t = View   <$> severalRecipesP t <*> servingP t <*> stepP t <*> conversionP t
+shopP    t = Shop   <$> severalRecipesP t <*> servingP t
 dataDirP _ = pure DataDir
 
-
 -- | @groupByTagsP is flag for grouping recipes by tags
 groupByTagsP :: Translator -> Parser Bool
 groupByTagsP t = switch
@@ -425,11 +397,6 @@
 fileNameP t = strArgument (  metavar (t Str.fileNameMetavar)
                           <> help    (t Str.fileNameDesc))
 
--- | @severalFilesP parses several file names at once
---   and returns th parser of a list of names
-severalFilesP :: Translator -> Parser [String]
-severalFilesP t = many (fileNameP t)
-
 -- | @severalRecipesP parses several recipe names at once
 --   and returns the parser of list of names
 severalRecipesP :: Translator -> Parser [String]
@@ -483,6 +450,6 @@
 
 -- @prsr is the main parser of all CLI arguments.
 commandPI :: Translator -> ParserInfo Command
-commandPI t = info ( helper <*> versionOption <*> (optP t))
+commandPI t = info ( helper <*> versionOption <*> optP t)
           $  fullDesc
           <> progDesc (t Str.progDesc)
diff --git a/data/config.hs b/data/config.hs
--- a/data/config.hs
+++ b/data/config.hs
@@ -8,8 +8,8 @@
 -- Set to 0 for no default.
 , defaultServingSize = 0
 
--- Recipes file name and relative location.
--- Default is "recipes.herms"
+-- Recipes file name relative to the user's XDG data dir, generally
+-- ~/.local/share/herms on Linux systems. Default is "recipes.herms".
 , recipesFile = "recipes.herms"
 , language = "english"
 }
diff --git a/herms.cabal b/herms.cabal
--- a/herms.cabal
+++ b/herms.cabal
@@ -16,7 +16,7 @@
 -- PVP summary:      +-+------- New features or improvements with significant API change
 --                   | | +----- Bugfixes and improvements with minor change to API
 --                   | | | +--- Bugfixes and improvements with no change to API
-version:             1.9.0.3
+version:             1.9.0.4
 
 -- A short (one-line) description of the package.
 synopsis:            A command-line manager for delicious kitchen recipes
@@ -65,10 +65,12 @@
   -- .hs or .lhs file containing the Main module.
   main-is:             herms.hs
 
+  Ghc-Options:         -W -Wcompat
+                       -Wunrecognised-warning-flags
+
   -- Modules included in this executable, other than Main.
   other-modules:       Utils
                      , AddCLI
-                     , AddFile
                      , RichText
                      , ReadConfig
                      , Types
@@ -85,15 +87,16 @@
   -- Other library packages from which modules are imported.
   build-depends:       ansi-terminal >= 0.7.0 && <= 0.8.1
                      , base >=4.8 && <5
-                     , brick >= 0.19 && <= 0.38
+                     , brick >= 0.19 && <= 0.39
                      , directory >= 0.0
+                     , filepath >= 1.4 && < 1.5
                      , microlens >=0.4 && <0.5
                      , microlens-th >=0.4 && <0.5
                      , mtl >= 2.2.1 && < 2.3
                      , optparse-applicative >=0.14 && <0.15
                      , semigroups >= 0.18.3 && < 0.19
                      , split >=0.2 && <0.3
-                     , vty >=5.15 && <= 5.22
+                     , vty >=5.15 && <= 5.23
 
 
   -- Directories containing source files.
diff --git a/src/AddCLI.hs b/src/AddCLI.hs
--- a/src/AddCLI.hs
+++ b/src/AddCLI.hs
@@ -3,7 +3,6 @@
 {-# LANGUAGE RankNTypes #-}
 module AddCLI where
 
-import Control.Monad
 import Lens.Micro
 import Lens.Micro.TH
 import qualified Graphics.Vty as V
@@ -73,23 +72,23 @@
         ui = C.center $
             str (t Str.tuiTitle) <=>
             str " " <=>
-            (str (t Str.tuiName) <+> (hLimit 62 e1)) <=>
+            (str (t Str.tuiName) <+> hLimit 62 e1) <=>
             str " " <=>
-            (str (t Str.tuiDesc) <+> (hLimit 62 $ vLimit 4 e2)) <=>
+            (str (t Str.tuiDesc) <+> hLimit 62 (vLimit 4 e2)) <=>
             str " " <=>
-            (str (t Str.tuiServingSize) <+> (hLimit 3 e3)) <=>
+            (str (t Str.tuiServingSize) <+> hLimit 3 e3) <=>
             str " " <=>
             str (t Str.tuiHeaders) <=>
             (str (t Str.tuiIngrs)
-              <+> (hLimit 7 $ vLimit 7 e4)
-              <+> (hLimit 9 $ vLimit 7 e5)
-              <+> (hLimit 28 $ vLimit 7 e6)
-              <+> (hLimit 18 $ vLimit 7 e7))
+              <+> hLimit 7 (vLimit 7 e4)
+              <+> hLimit 9 (vLimit 7 e5)
+              <+> hLimit 28 (vLimit 7 e6)
+              <+> hLimit 18 (vLimit 7 e7))
               <=>
             str " " <=>
-            (str (t Str.tuiDirs) <+> (hLimit 62 $ vLimit 8 e8)) <=>
+            (str (t Str.tuiDirs) <+> hLimit 62 (vLimit 8 e8)) <=>
             str " " <=>
-            (str (t Str.tuiTags) <+> (hLimit 62 $ vLimit 1 e9)) <=>
+            (str (t Str.tuiTags) <+> hLimit 62 (vLimit 1 e9)) <=>
             str " " <=>
             str (t Str.tuiHelp1) <=>
             str (t Str.tuiHelp2) <=>
@@ -105,23 +104,23 @@
 
         -- Ctrl + <Arrow Keys>
         V.EvKey V.KDown [V.MCtrl] ->
-          M.continue $ st & focusRing %~ (determineNextFocus FocusDown st)
+          M.continue $ st & focusRing %~ determineNextFocus FocusDown st
         V.EvKey V.KUp [V.MCtrl] ->
-          M.continue $ st & focusRing %~ (determineNextFocus FocusUp st)
+          M.continue $ st & focusRing %~ determineNextFocus FocusUp st
         V.EvKey V.KRight [V.MCtrl] ->
-          M.continue $ st & focusRing %~ (determineNextFocus FocusRight st)
+          M.continue $ st & focusRing %~ determineNextFocus FocusRight st
         V.EvKey V.KLeft [V.MCtrl] ->
-          M.continue $ st & focusRing %~ (determineNextFocus FocusLeft st)
+          M.continue $ st & focusRing %~ determineNextFocus FocusLeft st
 
         -- Meta + <h-j-k-l>
         V.EvKey (V.KChar 'h') [V.MMeta] ->
-          M.continue $ st & focusRing %~ (determineNextFocus FocusLeft st)
+          M.continue $ st & focusRing %~ determineNextFocus FocusLeft st
         V.EvKey (V.KChar 'j') [V.MMeta] ->
-          M.continue $ st & focusRing %~ (determineNextFocus FocusDown st)
+          M.continue $ st & focusRing %~ determineNextFocus FocusDown st
         V.EvKey (V.KChar 'k') [V.MMeta] ->
-          M.continue $ st & focusRing %~ (determineNextFocus FocusUp st)
+          M.continue $ st & focusRing %~ determineNextFocus FocusUp st
         V.EvKey (V.KChar 'l') [V.MMeta] ->
-          M.continue $ st & focusRing %~ (determineNextFocus FocusRight st)
+          M.continue $ st & focusRing %~ determineNextFocus FocusRight st
 
         _ -> M.continue =<< case F.focusGetCurrent (st^.focusRing) of
                Just RecipeName -> T.handleEventLensed st edit1 E.handleEditorEvent ev
@@ -140,49 +139,49 @@
 determineNextFocus action st =
   case action of
     FocusDown -> case currentFocus of
-        Just RecipeName -> (F.focusNext)
-        Just Description -> (F.focusNext)
-        Just ServingSize -> (F.focusNext)
-        Just IngrAmount -> (F.focusNext . F.focusNext . F.focusNext . F.focusNext)
-        Just IngrUnit -> (F.focusNext . F.focusNext . F.focusNext)
-        Just IngrName -> (F.focusNext . F.focusNext)
-        Just IngrAttr -> (F.focusNext)
-        Just Directions -> (F.focusNext)
-        Just Tags -> (F.focusNext)
-        Nothing -> (F.focusNext)
+        Just RecipeName -> F.focusNext
+        Just Description -> F.focusNext
+        Just ServingSize -> F.focusNext
+        Just IngrAmount -> F.focusNext . F.focusNext . F.focusNext . F.focusNext
+        Just IngrUnit -> F.focusNext . F.focusNext . F.focusNext
+        Just IngrName -> F.focusNext . F.focusNext
+        Just IngrAttr -> F.focusNext
+        Just Directions -> F.focusNext
+        Just Tags -> F.focusNext
+        Nothing -> F.focusNext
     FocusUp -> case currentFocus of
-        Just RecipeName -> (F.focusPrev)
-        Just Description -> (F.focusPrev)
-        Just ServingSize -> (F.focusPrev)
-        Just IngrAttr -> (F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev)
-        Just IngrName -> (F.focusPrev . F.focusPrev . F.focusPrev)
-        Just IngrUnit -> (F.focusPrev . F.focusPrev)
-        Just IngrAmount -> (F.focusPrev)
-        Just Directions -> (F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev)
-        Just Tags -> (F.focusPrev)
-        Nothing -> (F.focusPrev)
+        Just RecipeName -> F.focusPrev
+        Just Description -> F.focusPrev
+        Just ServingSize -> F.focusPrev
+        Just IngrAttr -> F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev
+        Just IngrName -> F.focusPrev . F.focusPrev . F.focusPrev
+        Just IngrUnit -> F.focusPrev . F.focusPrev
+        Just IngrAmount -> F.focusPrev
+        Just Directions -> F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev
+        Just Tags -> F.focusPrev
+        Nothing -> F.focusPrev
     FocusLeft -> case currentFocus of
-        Just RecipeName -> (F.focusNext . F.focusNext)
-        Just Description -> (F.focusNext)
-        Just ServingSize -> (F.focusNext)
-        Just IngrAmount -> (F.focusNext . F.focusNext . F.focusNext)
-        Just IngrUnit -> (F.focusPrev)
-        Just IngrName -> (F.focusPrev)
-        Just IngrAttr -> (F.focusPrev)
-        Just Directions -> (F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev)
-        Just Tags -> (F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev)
-        Nothing -> (F.focusNext)
+        Just RecipeName -> F.focusNext . F.focusNext
+        Just Description -> F.focusNext
+        Just ServingSize -> F.focusNext
+        Just IngrAmount -> F.focusNext . F.focusNext . F.focusNext
+        Just IngrUnit -> F.focusPrev
+        Just IngrName -> F.focusPrev
+        Just IngrAttr -> F.focusPrev
+        Just Directions -> F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev
+        Just Tags -> F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev
+        Nothing -> F.focusNext
     FocusRight -> case currentFocus of
-        Just RecipeName -> (F.focusNext . F.focusNext)
-        Just Description -> (F.focusNext)
-        Just ServingSize -> (F.focusNext)
-        Just IngrAmount -> (F.focusNext)
-        Just IngrUnit -> (F.focusNext)
-        Just IngrName -> (F.focusNext)
-        Just IngrAttr -> (F.focusPrev . F.focusPrev . F.focusPrev)
-        Just Directions -> (F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev)
-        Just Tags -> (F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev)
-        Nothing -> (F.focusNext)
+        Just RecipeName -> F.focusNext . F.focusNext
+        Just Description -> F.focusNext
+        Just ServingSize -> F.focusNext
+        Just IngrAmount -> F.focusNext
+        Just IngrUnit -> F.focusNext
+        Just IngrName -> F.focusNext
+        Just IngrAttr -> F.focusPrev . F.focusPrev . F.focusPrev
+        Just Directions -> F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev
+        Just Tags -> F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev . F.focusPrev
+        Nothing -> F.focusNext
   where currentFocus = F.focusGetCurrent $ st^.focusRing
 
 
@@ -217,10 +216,10 @@
           , M.appAttrMap = const theMap
           }
 
-getEdit :: Translator -> String -> String -> String -> String -> String -> String -> String -> String -> String -> IO ([[String]])
+getEdit :: Translator -> String -> String -> String -> String -> String -> String -> String -> String -> String -> IO [[String]]
 getEdit t name desc serving amounts units ingrs attrs dirs tags = do
   st <- M.defaultMain (theApp t) (initialState name desc serving amounts units ingrs attrs dirs tags)
-  return $ [ E.getEditContents $ st^.edit1
+  return [ E.getEditContents $ st^.edit1
              , E.getEditContents $ st^.edit2
              , E.getEditContents $ st^.edit3
              , E.getEditContents $ st^.edit4
@@ -231,10 +230,10 @@
              , E.getEditContents $ st^.edit9
              ]
 
-getAddInput :: Translator -> IO ([[String]])
-getAddInput t = do 
+getAddInput :: Translator -> IO [[String]]
+getAddInput t = do
   st <- M.defaultMain (theApp t) (initialState "" "" "" "" "" "" "" "" "")
-  return $ [ E.getEditContents $ st^.edit1
+  return [ E.getEditContents $ st^.edit1
              , E.getEditContents $ st^.edit2
              , E.getEditContents $ st^.edit3
              , E.getEditContents $ st^.edit4
diff --git a/src/AddFile.hs b/src/AddFile.hs
deleted file mode 100644
--- a/src/AddFile.hs
+++ /dev/null
@@ -1,7 +0,0 @@
-module AddFile where
-
-import UnitConversions
-
-readRecipeFileData :: String -> [[String]]
-readRecipeFileData _ = [["Nazzzme"],["Des lol","djdj",""],["2"],["2","1 2/2"],["units","units"],["name","name2"],["lol","ehe"],["jejej","ejeje","kks","lslsl","slsl"],["spicy licy lol"]]
-
diff --git a/src/Lang/French.hs b/src/Lang/French.hs
--- a/src/Lang/French.hs
+++ b/src/Lang/French.hs
@@ -9,7 +9,7 @@
   | is tuiDesc        = "   Description: "
   | is tuiServingSize = "       Portion: "
   | is tuiHeaders     = "                  qté.   unité              nom                 attribut"
-  | is tuiIngrs       = "  Ingrédients: \n(un par ligne)  " 
+  | is tuiIngrs       = "  Ingrédients: \n(un par ligne)  "
   | is tuiDirs        = "   Directions: \n(un par ligne)  "
   | is tuiTags        = "     Mots-clés: "
   | is tuiHelp1       = "                      Tab / Shift+Tab           - Champ suivant / précédent"
@@ -19,11 +19,11 @@
   | is headerServs    = "\nPortions: "
   | is headerIngrs    = "\nIngrédients:\n"
   | is saveRecipeYesNoEdit = "Enregister la recette? (O)ui  (N)on (E)diter"
-  | is y              = "o" 
+  | is y              = "o"
   | is yCap           = "O"
-  | is n              = "n" 
+  | is n              = "n"
   | is nCap           = "N"
-  | is e              = "e" 
+  | is e              = "e"
   | is eCap           = "E"
   | is recipeSaved    = "Recette enregistrée!"
   | is changesDiscarded = "Modifications annulées."
diff --git a/src/Lang/Pirate.hs b/src/Lang/Pirate.hs
--- a/src/Lang/Pirate.hs
+++ b/src/Lang/Pirate.hs
@@ -8,7 +8,7 @@
   | is tuiName        = "  Giv'r a name: "
   | is tuiDesc        = "    Describin': "
   | is tuiServingSize = "  Servin' size: "
-  | is tuiIngrs       = "     Reagents: \n(one per line)  " 
+  | is tuiIngrs       = "     Reagents: \n(one per line)  "
   | is tuiHelp1       = "                      Tab / Shift+Tab           - Next / Previous bay"
   | is tuiHelp2       = "                      Ctrl + <Arrow keys>       - Navigate the sea"
   | is tuiHelp3       = "                      [Meta or Alt] + <h-j-k-l> - Navigate the sea"
diff --git a/src/Lang/Portuguese.hs b/src/Lang/Portuguese.hs
--- a/src/Lang/Portuguese.hs
+++ b/src/Lang/Portuguese.hs
@@ -8,7 +8,7 @@
   | is tuiName        = "  Giv'r a name: "
   | is tuiDesc        = "    Describin': "
   | is tuiServingSize = "  Servin' size: "
-  | is tuiIngrs       = "     Reagents: \n(one per line)  " 
+  | is tuiIngrs       = "     Reagents: \n(one per line)  "
   | is tuiHelp1       = "                      Tab / Shift+Tab           - Next / Previous bay"
   | is tuiHelp2       = "                      Ctrl + <Arrow keys>       - Navigate the sea"
   | is tuiHelp3       = "                      [Meta or Alt] + <h-j-k-l> - Navigate the sea"
diff --git a/src/Lang/Strings.hs b/src/Lang/Strings.hs
--- a/src/Lang/Strings.hs
+++ b/src/Lang/Strings.hs
@@ -3,15 +3,15 @@
 --------------------------
 ---- Add Recipe TUI ------
 --------------------------
-  
+
 -- *** Note: Whitespace is important!!! ***
-  
+
 tuiTitle       = "                                    Herm's - Add a recipe"
 tuiName        = "          Name: "
 tuiDesc        = "   Description: "
 tuiServingSize = "  Serving size: "
 tuiHeaders     = "                  qty.   unit               name                attribute"
-tuiIngrs       = "  Ingredients: \n(one per line)  " 
+tuiIngrs       = "  Ingredients: \n(one per line)  "
 tuiDirs        = "   Directions: \n(one per line)  "
 tuiTags        = "          Tags: "
 tuiHelp1       = "                      Tab / Shift+Tab           - Next / Previous field"
@@ -32,13 +32,13 @@
 
 saveRecipeYesNoEdit = "Save recipe? (Y)es  (N)o  (E)dit"
 
-y    = "y" 
+y    = "y"
 yCap = "Y"
 
-n    = "n" 
+n    = "n"
 nCap = "N"
 
-e    = "e" 
+e    = "e"
 eCap = "E"
 
 recipeSaved = "Recipe saved!"
@@ -66,7 +66,7 @@
 --------------------------
 --   Options and Flags  --
 --------------------------
- 
+
 group      = "group"
 groupShort = 'g'
 groupDesc  = "group recipes by tags"
@@ -104,7 +104,7 @@
 --------------------------
 -- Commands             --
 --------------------------
- 
+
 list     = "list"
 listDesc = "list recipes"
 
@@ -130,7 +130,7 @@
 shoppingDesc = "generate a shopping list for given recipes"
 
 datadir     = "datadir"
-datadirDesc = "show location of recipe and config files"
+datadirDesc = "show locations of recipe and config files"
 
 version      = "version"
 versionShort = 'v'
@@ -139,5 +139,5 @@
 --------------------------
 --     Misc             --
 --------------------------
- 
+
 progDesc = "HeRM's: a Haskell-based Recipe Manager. Type \"herms --help\" for options"
diff --git a/src/ReadConfig.hs b/src/ReadConfig.hs
--- a/src/ReadConfig.hs
+++ b/src/ReadConfig.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE LambdaCase #-}
+
 module ReadConfig where
 
 import UnitConversions
@@ -8,12 +10,14 @@
 import Data.List.Split
 import Lang.Pirate
 import Lang.French
-import Paths_herms
+import System.FilePath ((</>))
+import System.Directory
+import Paths_herms hiding (getDataDir) -- This module is generated by cabal
 
 ------------------------------
 ------- Config Types ---------
 ------------------------------
-  
+
 -- TODO Allow record synonyms with that fancy stuff
 
 data ConfigInfo = ConfigInfo
@@ -26,9 +30,11 @@
 data Config = Config
   { defaultUnit'        :: Conversion
   , defaultServingSize' :: Int
+  , dataDir             :: String
+  , configDir           :: String
   , recipesFile'        :: String
   , translator          :: String -> String
-  } 
+  }
 
 data Language = English
               | Pirate
@@ -41,7 +47,7 @@
 ---- Exception Handling ------
 ------------------------------
 
-data ConfigParseError = ConfigParseError 
+data ConfigParseError = ConfigParseError
   deriving Typeable
 
 instance Show ConfigParseError where
@@ -87,35 +93,83 @@
 
 getLang :: ConfigInfo -> Language
 getLang c
-  | isIn englishSyns = English
   -- | isIn portugueseSyns = Portuguese
   | isIn pirateSyns  = Pirate
   -- | isIn frenchSyns = French
   | isIn frenchSyns  = French
+  | otherwise        = English
   where isIn = elem (map toLower $ language c)
 
 getTranslator :: Language -> Translator
 getTranslator lang = case lang of
-                       English -> id :: String -> String
-                       Pirate  -> pirate
-                       French  -> french
+                       Pirate    -> pirate
+                       French    -> french
+                       _         -> id :: String -> String
 
 dropComments :: String -> String
 dropComments = unlines . map (head . splitOn "--") . lines
 
-processConfig :: ConfigInfo -> Config
-processConfig raw = Config
+processConfig :: FilePath -> FilePath -> ConfigInfo -> Config
+processConfig dataDir configDir raw = Config
   { defaultUnit'        = defaultUnit raw
   , defaultServingSize' = defaultServingSize raw
-  , recipesFile'        = recipesFile raw
+  , recipesFile'        = dataDir </> recipesFile raw
   , translator          = getTranslator $ getLang raw
+  , dataDir             = dataDir
+  , configDir           = configDir
   }
 
+-- | The directory of the config.hs file. Its location is dictated by
+--   <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG
+--   Base Directory Specification>.
+getConfigDir :: IO FilePath
+getConfigDir = getXdgDirectory XdgConfig "herms"
+
+-- | The directory of the recipes.herms file.
+getDataDir :: IO FilePath
+getDataDir = getXdgDirectory XdgData "herms"
+
+-- | Create a directory if it doesn't exist, ensure it is readable,
+-- writable, and executable.
+directoryWithPermissions :: FilePath -> IO ()
+directoryWithPermissions dir = do
+  createDirectoryIfMissing True dir
+  setPermissions dir $
+    setOwnerReadable True $
+    setOwnerWritable True $
+    setOwnerExecutable True
+    emptyPermissions
+
+writeDefaultFile :: String -> FilePath -> IO ()
+writeDefaultFile name path = do
+  putStrLn $ "Couldn't find " ++ path
+  templatePath <- getDataFileName name
+  putStrLn $ "Copying default from " ++ templatePath
+  copyFile templatePath path
+
+-- | @readFileOrDefault attempts to read a file from a path. If that file
+-- doesn't exist, it copies a default version that was installed by cabal
+-- with @writeDefaultFile.
+readFileOrDefault :: String -> FilePath -> IO String
+readFileOrDefault name path = 
+  (try (readFile path) :: IO (Either IOError String)) >>=
+    \case
+      Left _ -> writeDefaultFile name path >> readFile path
+      Right content -> return content
+
 getConfig :: IO Config
 getConfig = do
-  fileName <- getDataFileName "config.hs"
-  contents <- readFile fileName
+
+  -- Create configuration and data directories
+  configDir <- getConfigDir
+  dataDir   <- getDataDir
+  mapM_ directoryWithPermissions [configDir, dataDir]
+
+  -- Try to read configuration file
+  contents  <- readFileOrDefault "config.hs" (configDir </> "config.hs")
+
+  -- Parse the configuration
   let result = TR.readEither (dropComments contents) :: Either String ConfigInfo
   case result of
-    Left str -> throw ConfigParseError
-    Right r  -> return (processConfig r)
+    Left  _ -> throw ConfigParseError
+    Right r -> return (processConfig dataDir configDir r)
diff --git a/src/RichText.hs b/src/RichText.hs
--- a/src/RichText.hs
+++ b/src/RichText.hs
@@ -7,7 +7,6 @@
 import Data.String
 import System.Console.ANSI
 import System.IO
-import Debug.Trace
 
 class Text t where
   toStr :: Bool -> t -> String
diff --git a/src/UnitConversions.hs b/src/UnitConversions.hs
--- a/src/UnitConversions.hs
+++ b/src/UnitConversions.hs
@@ -1,9 +1,7 @@
 module UnitConversions where
 
-import Data.List
-import Data.Ratio
 import Data.Char (toLower)
-import Types 
+import Types
 
 data Conversion = Metric | Imperial | None deriving (Show, Read, Eq)
 
@@ -108,7 +106,7 @@
         Just "pint"  -> ingr{quantity = qty * 473, unit = "mL"}
         Just "quart" -> ingr{quantity = qty * 946, unit = "mL"}
         Just "gallon"-> ingr{quantity = qty * 3.785, unit = "L"}
-        Nothing      -> ingr
+        _            -> ingr
     where
         units = unit ingr
         qty = quantity ingr
