diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,6 @@
+# madlang
+
+## 4.0.2.9
+
+  * Use `getUserAppDataDirectory` instead of relying on the `$HOME` variable,
+    providing better compatibility on Windows. 
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -3,7 +3,6 @@
     main ) where
 
 import           Data.Maybe
-import           Data.Semigroup
 import qualified Data.Text                    as T
 import qualified Data.Text.Lazy               as TL
 import qualified Data.Text.Lazy.IO            as TLIO
diff --git a/app/Text/Madlibs/Packaging/Fetch.hs b/app/Text/Madlibs/Packaging/Fetch.hs
--- a/app/Text/Madlibs/Packaging/Fetch.hs
+++ b/app/Text/Madlibs/Packaging/Fetch.hs
@@ -13,7 +13,8 @@
 import           Control.Monad           (unless)
 import           Network.HTTP.Client     hiding (decompress)
 import           Network.HTTP.Client.TLS (tlsManagerSettings)
-import           System.Directory        (removeFile, renameDirectory)
+import           System.Directory        (getAppUserDataDirectory, removeFile,
+                                          renameDirectory)
 import           System.Environment      (getEnv)
 import           System.Info             (os)
 
@@ -33,8 +34,7 @@
     response <- responseBody <$> httpLbs (initialRequest { method = "GET" }) manager
 
     putStrLn "unpacking libraries..."
-    home <- getEnv "HOME"
-    let packageDir = if os /= "mingw32" then home ++ "/.madlang" else home ++ "\\.madlang"
+    packageDir <- getAppUserDataDirectory "madlang"
     let options = OptDestination packageDir
     extractFilesFromArchive [options] (toArchive response)
 
@@ -71,8 +71,7 @@
     response <- responseBody <$> httpLbs (initialRequest { method = "GET" }) manager
 
     putStrLn "unpacking libraries..."
-    home <- getEnv "HOME"
-    let packageDir = if os /= "mingw32" then home ++ "/.madlang" else home ++ "\\.madlang"
+    packageDir <- getAppUserDataDirectory "madlang"
     Tar.unpack packageDir . Tar.read . decompress $ response
 
 cleanPackages :: IO ()
diff --git a/madlang.cabal b/madlang.cabal
--- a/madlang.cabal
+++ b/madlang.cabal
@@ -1,6 +1,6 @@
-cabal-version: >=1.10
+cabal-version: 1.18
 name: madlang
-version: 4.0.2.8
+version: 4.0.2.9
 license: BSD3
 license-file: LICENSE
 copyright: Copyright: (c) 2016-2018 Vanessa McHale
@@ -16,12 +16,13 @@
 category: Web
 build-type: Custom
 extra-source-files:
-    README.md
     test/templates/*.mad
     test/templates/err/*.mad
     demo/*.mad
     cabal.project.local
     man/madlang.1
+extra-doc-files: README.md
+                 CHANGELOG.md
 
 source-repository head
     type: darcs
@@ -61,7 +62,7 @@
     default-language: Haskell2010
     ghc-options: -Wall
     build-depends:
-        base >=4.9 && <5,
+        base >=4.11 && <5,
         megaparsec >=6.0,
         text -any,
         template-haskell -any,
@@ -93,7 +94,7 @@
     default-language: Haskell2010
     ghc-options: -Wall
     build-depends:
-        base >=4.9,
+        base >=4.11,
         madlang -any,
         optparse-applicative -any,
         text -any,
diff --git a/man/madlang.1 b/man/madlang.1
--- a/man/madlang.1
+++ b/man/madlang.1
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.1.3
+.\" Automatically generated by Pandoc 2.2.3.2
 .\"
 .TH "madlang (1)" "" "" "" ""
 .hy
diff --git a/src/Text/Madlibs/Ana/Parse.hs b/src/Text/Madlibs/Ana/Parse.hs
--- a/src/Text/Madlibs/Ana/Parse.hs
+++ b/src/Text/Madlibs/Ana/Parse.hs
@@ -17,7 +17,6 @@
 import           Control.Monad.State
 import qualified Data.Map                    as M
 import           Data.Maybe
-import           Data.Semigroup
 import qualified Data.Text                   as T
 import           Data.Void
 import           Text.Madlibs.Ana.ParseUtils
diff --git a/src/Text/Madlibs/Ana/ParseUtils.hs b/src/Text/Madlibs/Ana/ParseUtils.hs
--- a/src/Text/Madlibs/Ana/ParseUtils.hs
+++ b/src/Text/Madlibs/Ana/ParseUtils.hs
@@ -19,7 +19,6 @@
 import           Data.List
 import qualified Data.Map                    as M
 import           Data.Maybe                  (mapMaybe)
-import           Data.Semigroup
 import qualified Data.Set                    as S
 import qualified Data.Text                   as T
 import           Data.Text.Titlecase
diff --git a/src/Text/Madlibs/Ana/Resolve.hs b/src/Text/Madlibs/Ana/Resolve.hs
--- a/src/Text/Madlibs/Ana/Resolve.hs
+++ b/src/Text/Madlibs/Ana/Resolve.hs
@@ -18,11 +18,9 @@
 import           Control.Monad               (replicateM, void)
 import           Control.Monad.IO.Class      (MonadIO, liftIO)
 import           Control.Monad.Random.Class
-import           Data.Semigroup
 import qualified Data.Text                   as T
 import           Data.Void
 import           System.Directory
-import           System.Environment
 import           System.Info                 (os)
 import           Text.Madlibs.Ana.Parse
 import           Text.Madlibs.Ana.ParseUtils
@@ -42,7 +40,7 @@
 -- | Generate text from file with inclusions
 getInclusionCtx :: (MonadIO m) => Bool -> [T.Text] -> FilePath -> FilePath -> m (Either (ParseError Char (ErrorFancy Void)) [(Key, RandTok)])
 getInclusionCtx isTree ins folder filepath = liftIO $ do
-    libDir <- do { home <- getEnv "HOME" ; pure (home <> (pathSep : ".madlang" <> pure pathSep)) }
+    libDir <- do { pathDir <- getAppUserDataDirectory "madlang" ; pure ((pathDir <> pure pathSep)) }
     file <- catch (readFile' (folder ++ filepath)) (pure (readLibFile (libDir <> folder <> filepath)) :: IOException -> IO T.Text)
     let filenames = map T.unpack $ either (error . show) id $ parseInclusions filepath file -- TODO pass up errors correctly
     let resolveKeys file' = fmap (first (((T.pack . (<> "-")) . dropExtension) file' <>))
@@ -50,7 +48,7 @@
     let ctx = zipWith resolveKeys filenames <$> sequence ctxPure
     catch
         (parseCtx isTree ins (mconcat . either (pure []) id $ ctx) (folder ++ filepath))
-        (pure (do { home <- getEnv "HOME" ; parseCtx isTree ins (mconcat . either (pure []) id $ ctx) (home <> (pathSep : ".madlang") <> [pathSep] <> folder <> filepath) }) :: IOException -> IO (Either (ParseError Char (ErrorFancy Void)) [(Key, RandTok)]))
+        (pure (do { pathDir <- getAppUserDataDirectory "madlang" ; parseCtx isTree ins (mconcat . either (pure []) id $ ctx) (pathDir <> [pathSep] <> folder <> filepath) }) :: IOException -> IO (Either (ParseError Char (ErrorFancy Void)) [(Key, RandTok)]))
 
 pathSep :: Char
 pathSep | os == "windows" = '\\'
diff --git a/src/Text/Madlibs/Generate/TH.hs b/src/Text/Madlibs/Generate/TH.hs
--- a/src/Text/Madlibs/Generate/TH.hs
+++ b/src/Text/Madlibs/Generate/TH.hs
@@ -12,15 +12,14 @@
 
 import           Control.Arrow               (first)
 import           Data.FileEmbed              (embedStringFile)
-import           Data.Semigroup
 import qualified Data.Text                   as T
 import qualified Data.Text.IO                as TIO
 import           Data.Void
 import           Language.Haskell.TH         hiding (Dec)
 import           Language.Haskell.TH.Quote
 import           Language.Haskell.TH.Syntax  (lift)
-import           System.Directory            (doesFileExist)
-import           System.Environment          (getEnv)
+import           System.Directory            (doesFileExist,
+                                              getAppUserDataDirectory)
 import           Text.Madlibs.Ana.Parse
 import           Text.Madlibs.Ana.Resolve    (pathSep)
 import           Text.Madlibs.Internal.Types (Key, RandTok)
@@ -69,11 +68,11 @@
 madCtxCheck folder path = do
     let tryPath = folder ++ path
     local <- runIO $ doesFileExist tryPath
-    home <- runIO $ getEnv "HOME"
+    pathDir <- runIO $ getAppUserDataDirectory "madlang"
     if local then
         madCtx folder path
     else
-        madCtx (home ++ (pathSep : (".madlang" ++ pure pathSep))) path
+        madCtx (pathDir ++ pure pathSep) path
 
 ctx :: [FilePath] -> [[(Key, RandTok)]] -> [[(Key, RandTok)]]
 ctx = zipWith resolveKeys
diff --git a/src/Text/Madlibs/Internal/Types.hs b/src/Text/Madlibs/Internal/Types.hs
--- a/src/Text/Madlibs/Internal/Types.hs
+++ b/src/Text/Madlibs/Internal/Types.hs
@@ -18,7 +18,6 @@
 import           Data.Binary                (Binary)
 import           Data.Function
 import           Data.Functor.Foldable.TH   (makeBaseFunctor)
-import           Data.Semigroup
 import qualified Data.Text                  as T
 import           GHC.Generics               (Generic)
 import           Instances.TH.Lift          ()
@@ -62,7 +61,6 @@
 -- > (List [(0.5,"Hello you"), (0.5, "Hello me")])
 instance Monoid RandTok where
     mempty = Value ""
-    mappend = (<>)
 
 -- TODO make this a map instead of keys for faster parse.
 -- | State monad providing context, i.e. function we've already called before
