diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,54 @@
+# 1.1.1.0
+
+* Expose `lookupTemplate` and `splitTemplatePath`
+
+* Bump dependency bounds for 9.4
+
+# 1.1
+
+* Remove pandoc and pandocBS
+
+* Stop exporting readProcessWithExitCode'
+
+* Remove -S and --no-wrap arguments to pandoc for compatibility with both 1.x
+  and 2.x versions of the pandoc command line tool
+
+* Bump map-syntax lower bound to fix 8.4 build problem
+
+# 1.0.1.3
+
+* Add Semigroup instances to support GHC 8.4
+
+# 1.0.1.0
+
+* Change benchmark from an executable section to a benchmark section in the
+  cabal file.  This eliminates the criterion dependency when doing "cabal
+  install heist".
+* Export manyWith
+
+# 1.0.0.1
+
+* Drop the dependency on `errors` packages from heist testsuite and benchmark
+* Fix nested splice namespace warning bug (issue #85)
+
+# 1.0.0.0
+
+* Switch from MonadCatchIO-transformers to monad-control for Snap 1.0
+
+# 0.14.0
+
+See http://snapframework.com/blog/2014/09/24/heist-0.14-released
+
+* Add namespace support (hcNamespace and hcErrorNotBound)
+* Add tellSpliceError for generalized error reporting
+* Restructured HeistConfig, export lenses instead of field accessors
+* Moved old HeistConfig into SpliceConfig
+* Factored SpliceAPI module out into separate map-syntax package
+
+# 0.13.0
+
+See http://snapframework.com/blog/2013/09/09/snap-0.13-released
+
+* Simpler compiled splice API
+* New splice syntax
+
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # Heist
 
-[![Build Status](https://travis-ci.org/snapframework/heist.svg?branch=master)](https://travis-ci.org/snapframework/heist)
+[![GitHub CI](https://github.com/snapframework/heist/workflows/CI/badge.svg)](https://github.com/snapframework/heist/actions)
 
 Heist, part of the [Snap Framework](http://www.snapframework.com/), is a
 Haskell library for xml/html templating. It uses simple XML tags to bind
diff --git a/heist.cabal b/heist.cabal
--- a/heist.cabal
+++ b/heist.cabal
@@ -1,5 +1,6 @@
+cabal-version:  2.2
 name:           heist
-version:        1.1.0.1
+version:        1.1.1.0
 synopsis:       An Haskell template system supporting both HTML5 and XML.
 description:
     Heist is a powerful template system that supports both HTML5 and XML.
@@ -22,27 +23,25 @@
     .
     * Optional merging of multiple \<head\> tags defined anywhere in the
       document
-license:        BSD3
+license:        BSD-3-Clause
 license-file:   LICENSE
 author:         Doug Beardsley, Gregory Collins
 maintainer:     snap@snapframework.com
 build-type:     Simple
-cabal-version:  >= 1.8.0.4
 homepage:       http://snapframework.com/
 category:       Web, Snap
 
-Tested-With:
-  GHC == 7.4.2,
-  GHC == 7.6.3,
-  GHC == 7.8.4,
-  GHC == 7.10.3,
-  GHC == 8.0.1,
-  GHC == 8.2.2,
-  GHC == 8.4.3,
-  GHC == 8.6.1
+tested-with:
+  GHC == 8.6.5
+  GHC == 8.8.4
+  GHC == 8.10.7
+  GHC == 9.0.2
+  GHC == 9.2.5
+  GHC == 9.4.3
 
 extra-source-files:
   .ghci,
+  CHANGELOG.md,
   CONTRIBUTORS,
   docs/Makefile,
   docs/templates.css,
@@ -131,8 +130,28 @@
   test/templates-nscall/nscall.tpl,
   TODO
 
+common universal
+  default-language: Haskell2010
 
+  default-extensions:
+    DeriveDataTypeable
+    FlexibleInstances
+    GeneralizedNewtypeDeriving
+    MultiParamTypeClasses
+    OverloadedStrings
+    PackageImports
+    ScopedTypeVariables
+    TypeSynonymInstances
+
+  build-depends:
+    base >= 4.5 && < 4.18,
+
+  if !impl(ghc >= 8.0)
+    build-depends:
+      semigroups >= 0.16 && < 0.19,
+
 Library
+  import: universal
   hs-source-dirs: src
 
   exposed-modules:
@@ -160,51 +179,36 @@
     Heist.Interpreted.Internal
 
   build-depends:
-    aeson                      >= 0.6     && < 1.5,
-    attoparsec                 >= 0.10    && < 0.14,
-    base                       >= 4.5     && < 4.13,
+    aeson                      >= 0.6     && < 2.2,
+    attoparsec                 >= 0.10    && < 0.15,
     blaze-builder              >= 0.2     && < 0.5,
     blaze-html                 >= 0.4     && < 0.10,
-    bytestring                 >= 0.9     && < 0.11,
+    bytestring                 >= 0.9     && < 0.12,
     containers                 >= 0.2     && < 0.7,
     directory                  >= 1.1     && < 1.4,
     directory-tree             >= 0.10    && < 0.13,
-    dlist                      >= 0.5     && < 0.9,
+    dlist                      >= 0.5     && < 1.1,
     filepath                   >= 1.3     && < 1.5,
-    hashable                   >= 1.1     && < 1.3,
+    hashable                   >= 1.1     && < 1.5,
     lifted-base                >= 0.2     && < 0.3,
     map-syntax                 >= 0.3     && < 0.4,
     monad-control              >= 0.3     && < 1.1,
     mtl                        >= 2.0     && < 2.3,
     process                    >= 1.1     && < 1.7,
-    random                     >= 1.0.1.0 && < 1.2,
-    text                       >= 0.10    && < 1.3,
-    time                       >= 1.1     && < 1.10,
+    random                     >= 1.0.1.0 && < 1.3,
+    text                       >= 0.10    && < 2.1,
+    time                       >= 1.1     && < 1.13,
     transformers               >= 0.3     && < 0.6,
     transformers-base          >= 0.4     && < 0.5,
     unordered-containers       >= 0.1.4   && < 0.3,
     vector                     >= 0.9     && < 0.13,
-    xmlhtml                    >= 0.2.3.5 && < 0.3
-
-  if !impl(ghc >= 8.0)
-    build-depends: semigroups >= 0.16 && < 0.19
+    xmlhtml                    >= 0.2.3.5 && < 0.4,
+    indexed-traversable        >= 0.1.1   && < 0.2
 
-  if impl(ghc >= 6.12.0)
-    ghc-options: -Wall -fwarn-tabs -funbox-strict-fields
-                 -fno-warn-unused-do-bind
-  else
-    ghc-options: -Wall -fwarn-tabs -funbox-strict-fields
+  ghc-options: -Wall -fwarn-tabs -funbox-strict-fields
 
-  Extensions:
-    GeneralizedNewtypeDeriving,
-    PackageImports,
-    ScopedTypeVariables,
-    DeriveDataTypeable,
-    FlexibleInstances,
-    MultiParamTypeClasses,
+  default-extensions:
     UndecidableInstances,
-    OverloadedStrings,
-    TypeSynonymInstances,
     NoMonomorphismRestriction
 
 
@@ -213,20 +217,20 @@
   location: https://github.com/snapframework/heist.git
 
 Test-suite testsuite
+  import: universal
   hs-source-dirs: src test/suite
   type: exitcode-stdio-1.0
   main-is: TestSuite.hs
 
   build-depends:
     HUnit                      >= 1.2      && < 2,
-    QuickCheck                 >= 2        && < 2.13,
-    lens                       >= 4.3      && < 4.18,
+    QuickCheck                 >= 2        && < 2.15,
+    lens                       >= 4.3      && < 5.3,
     test-framework             >= 0.4      && < 0.9,
     test-framework-hunit       >= 0.2.7    && < 0.4,
     test-framework-quickcheck2 >= 0.2.12.1 && < 0.4,
     aeson,
     attoparsec,
-    base,
     bifunctors >= 5.3 && < 5.6,
     blaze-builder,
     blaze-html,
@@ -249,26 +253,24 @@
     transformers-base,
     unordered-containers,
     vector,
-    xmlhtml
-
-  if !impl(ghc >= 8.0)
-    build-depends: semigroups >= 0.16 && < 0.19
+    xmlhtml,
+    indexed-traversable
 
   if impl(ghc >= 7.8) && impl(ghc < 7.10)
     build-depends: transformers-compat >= 0.3 && < 0.7
 
   ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -threaded
-  Extensions: OverloadedStrings
 
 Benchmark benchmark
+  import: universal
   hs-source-dirs: src test/suite
   type: exitcode-stdio-1.0
   main-is: Benchmark.hs
 
   build-depends:
     HUnit,
-    criterion                 >= 1.0     && < 1.6,
-    criterion-measurement     >= 0.1     && < 0.2,
+    criterion                 >= 1.0,
+    criterion-measurement     >= 0.1,
     test-framework,
     test-framework-hunit,
 
@@ -276,7 +278,6 @@
 
     aeson,
     attoparsec,
-    base,
     blaze-builder,
     blaze-html,
     bytestring,
@@ -292,17 +293,15 @@
     mtl,
     process,
     random,
-    statistics                 >= 0.11    && < 0.16,
+    statistics                 >= 0.11,
     text,
     time,
     transformers,
     transformers-base,
     unordered-containers,
     vector,
-    xmlhtml
-
-  if !impl(ghc >= 8.0)
-    build-depends: semigroups >= 0.16 && < 0.19
+    xmlhtml,
+    indexed-traversable
 
   if impl(ghc >= 7.8) && impl(ghc < 7.10)
     build-depends: transformers-compat
@@ -310,14 +309,6 @@
   ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -threaded
                -fno-warn-unused-do-bind -rtsopts
 
-  Extensions:
-    GeneralizedNewtypeDeriving,
-    PackageImports,
-    ScopedTypeVariables,
-    DeriveDataTypeable,
-    FlexibleInstances,
-    MultiParamTypeClasses,
+  default-extensions:
     UndecidableInstances,
-    OverloadedStrings,
-    TypeSynonymInstances,
     NoMonomorphismRestriction
diff --git a/src/Heist.hs b/src/Heist.hs
--- a/src/Heist.hs
+++ b/src/Heist.hs
@@ -84,6 +84,10 @@
   , spliceErrorText
   , orError
   , Splices
+
+  -- * TPath functions
+  , lookupTemplate
+  , splitTemplatePath
   ) where
 
 
diff --git a/src/Heist/Common.hs b/src/Heist/Common.hs
--- a/src/Heist/Common.hs
+++ b/src/Heist/Common.hs
@@ -17,7 +17,7 @@
 import           Data.Hashable            (Hashable)
 import           Data.HashMap.Strict      (HashMap)
 import qualified Data.HashMap.Strict      as Map
-import           Data.List                (isSuffixOf)
+import           Data.List                (isSuffixOf, sort)
 import           Data.Map.Syntax
 import           Data.Maybe               (isJust)
 import           Data.Monoid              ((<>))
@@ -95,7 +95,7 @@
     let spliceError = SpliceError
                       { spliceHistory = _splicePath hs
                       , spliceTemplateFile = _curTemplateFile hs
-                      , visibleSplices = Map.keys $ _compiledSpliceMap hs
+                      , visibleSplices = sort $ Map.keys $ _compiledSpliceMap hs
                       , contextNode = node
                       , spliceMsg = msg
                       }
@@ -190,9 +190,9 @@
                -> Maybe (t, TPath)
 lookupTemplate nameStr ts tm = f (tm ts) path name
   where
-    (name:p) = case splitTemplatePath nameStr of
-                   [] -> [""]
-                   ps -> ps
+    (name, p) = case splitTemplatePath nameStr of
+                   []   -> ("", [])
+                   x:xs -> (x, xs)
     ctx = if B.isPrefixOf "/" nameStr then [] else _curContext ts
     path = p ++ ctx
     f = if '/' `BC.elem` nameStr
diff --git a/src/Heist/Compiled/Internal.hs b/src/Heist/Compiled/Internal.hs
--- a/src/Heist/Compiled/Internal.hs
+++ b/src/Heist/Compiled/Internal.hs
@@ -698,7 +698,7 @@
 withSplices splice splices runtimeAction =
     withLocalSplices splices' mempty splice
   where
-    splices' = mapV ($runtimeAction) splices
+    splices' = mapV ($ runtimeAction) splices
 
 
 ------------------------------------------------------------------------------
diff --git a/src/Heist/Interpreted/Internal.hs b/src/Heist/Interpreted/Internal.hs
--- a/src/Heist/Interpreted/Internal.hs
+++ b/src/Heist/Interpreted/Internal.hs
@@ -192,7 +192,7 @@
 runAttrSplice a@(k,v) = do
     splice <- getsHS (Map.lookup k . _attrSpliceMap)
     maybe (liftM (:[]) $ attSubst a)
-          (lift . flip evalStateT HE.empty . unRT . ($v)) splice
+          (lift . flip evalStateT HE.empty . unRT . ($ v)) splice
 
 
 ------------------------------------------------------------------------------
diff --git a/src/Heist/Splices/Json.hs b/src/Heist/Splices/Json.hs
--- a/src/Heist/Splices/Json.hs
+++ b/src/Heist/Splices/Json.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE BangPatterns        #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE FlexibleContexts #-}
 
 module Heist.Splices.Json (
   bindJson
@@ -11,7 +13,13 @@
 import           Data.Aeson
 import qualified Data.ByteString.Char8       as S
 import qualified Data.ByteString.Lazy.Char8  as L
+#if MIN_VERSION_aeson(2,0,0)
+import qualified Data.Aeson.KeyMap           as KM
+import qualified Data.Aeson.Key              as K
+import qualified Data.Foldable.WithIndex     as FI
+#else
 import qualified Data.HashMap.Strict         as Map
+#endif
 import           Data.Map.Syntax
 import           Data.Maybe
 import           Data.Text                   (Text)
@@ -89,7 +97,6 @@
 numToText :: ToJSON a => a -> Text
 numToText = T.decodeUtf8 . S.concat . L.toChunks . encode
 
-
 ------------------------------------------------------------------------------
 findExpr :: Text -> Value -> Maybe Value
 findExpr t = go (T.split (=='.') t)
@@ -97,7 +104,11 @@
     go [] !value     = Just value
     go (x:xs) !value = findIn value >>= go xs
       where
+#if MIN_VERSION_aeson(2,0,0)
+        findIn (Object obj) = KM.lookup (K.fromText x) obj
+#else
         findIn (Object obj) = Map.lookup x obj
+#endif
         findIn (Array arr)  = tryReadIndex >>= \i -> arr V.!? i
         findIn _            = Nothing
 
@@ -217,13 +228,23 @@
     --------------------------------------------------------------------------
     goObject obj = do
         start <- genericBindings
+#if MIN_VERSION_aeson(2,0,0)
+        let bindings = FI.ifoldl' (flip bindKvp) start  obj
+#else
         let bindings = Map.foldlWithKey' bindKvp start obj
+#endif
         lift $ runChildrenWith bindings
 
     --------------------------------------------------------------------------
+    
     bindKvp bindings k v =
-        let newBindings = do
-                T.append "with:" k    ## withValue v explodeTag
-                T.append "snippet:" k ## withValue v snippetTag
-                T.append "value:" k   ## withValue v valueTag
-        in  bindings >> newBindings
+#if MIN_VERSION_aeson(2,0,0)
+        let k' = K.toText k
+#else
+        let k' = k
+#endif
+            newBindings = do
+                T.append "with:" k'    ## withValue v explodeTag
+                T.append "snippet:" k' ## withValue v snippetTag
+                T.append "value:" k'   ## withValue v valueTag
+        in  bindings >> newBindings    
diff --git a/test/suite/Heist/Compiled/Tests.hs b/test/suite/Heist/Compiled/Tests.hs
--- a/test/suite/Heist/Compiled/Tests.hs
+++ b/test/suite/Heist/Compiled/Tests.hs
@@ -266,9 +266,9 @@
 
     H.assertEqual "namespace bind error test" (Left [ err1, err2, err3 ])  res
   where
-    err1 = "templates-nsbind/nsbinderror.tpl: No splice bound for h:invalid3\n   ... via templates-nsbind/nsbinderror.tpl: h:main2\nBound splices: h:sub h:recurse h:call h:main2 h:main\nNode: Element {elementTag = \"h:invalid3\", elementAttrs = [], elementChildren = []}"
-    err2 = "templates-nsbind/nsbinderror.tpl: No splice bound for h:invalid2\n   ... via templates-nsbind/nsbinderror.tpl: h:recurse\n   ... via templates-nsbind/nsbinderror.tpl: h:main\nBound splices: h:sub h:recurse h:call h:main2 h:main\nNode: Element {elementTag = \"h:invalid2\", elementAttrs = [], elementChildren = []}"
-    err3 = "templates-nsbind/nsbinderror.tpl: No splice bound for h:invalid1\nBound splices: h:call h:main2 h:main\nNode: Element {elementTag = \"h:invalid1\", elementAttrs = [], elementChildren = []}"
+    err1 = "templates-nsbind/nsbinderror.tpl: No splice bound for h:invalid3\n   ... via templates-nsbind/nsbinderror.tpl: h:main2\nBound splices: h:call h:main h:main2 h:recurse h:sub\nNode: Element {elementTag = \"h:invalid3\", elementAttrs = [], elementChildren = []}"
+    err2 = "templates-nsbind/nsbinderror.tpl: No splice bound for h:invalid2\n   ... via templates-nsbind/nsbinderror.tpl: h:recurse\n   ... via templates-nsbind/nsbinderror.tpl: h:main\nBound splices: h:call h:main h:main2 h:recurse h:sub\nNode: Element {elementTag = \"h:invalid2\", elementAttrs = [], elementChildren = []}"
+    err3 = "templates-nsbind/nsbinderror.tpl: No splice bound for h:invalid1\nBound splices: h:call h:main h:main2\nNode: Element {elementTag = \"h:invalid1\", elementAttrs = [], elementChildren = []}"
 
 
 ------------------------------------------------------------------------------
@@ -284,7 +284,7 @@
                          , Just "templates-nsbind/nsbinderror.tpl"
                          , "h:main2") ]
                (Just "templates-nsbind/nsbinderror.tpl")
-               ["h:sub","h:recurse","h:call","h:main2","h:main"]
+               ["h:call","h:main","h:main2","h:recurse","h:sub"]
                (X.Element "h:invalid3" [] [])
                "No splice bound for h:invalid3"
     err2 = SpliceError [ ( ["nsbinderror"]
@@ -294,12 +294,12 @@
                          , Just "templates-nsbind/nsbinderror.tpl"
                          ,"h:main") ]
                (Just "templates-nsbind/nsbinderror.tpl")
-               ["h:sub","h:recurse","h:call","h:main2","h:main"]
+               ["h:call","h:main","h:main2","h:recurse","h:sub"]
                (X.Element "h:invalid2" [] [])
                "No splice bound for h:invalid2"
     err3 = SpliceError []
                (Just "templates-nsbind/nsbinderror.tpl")
-               ["h:call","h:main2","h:main"]
+               ["h:call","h:main","h:main2"]
                (X.Element "h:invalid1" [] [])
                "No splice bound for h:invalid1"
 
@@ -334,8 +334,8 @@
       (Left $ Set.fromList [ err1, err2 ])
       (first Set.fromList res)
   where
-    err1 = "templates-nscall/_call.tpl: No splice bound for h:sub\nBound splices: h:call h:main2 h:main\nNode: Element {elementTag = \"h:sub\", elementAttrs = [], elementChildren = []}"
-    err2 = "templates-nscall/_invalid.tpl: No splice bound for h:invalid\nBound splices: h:call h:main2 h:main\nNode: Element {elementTag = \"h:invalid\", elementAttrs = [], elementChildren = []}"
+    err1 = "templates-nscall/_call.tpl: No splice bound for h:sub\nBound splices: h:call h:main h:main2\nNode: Element {elementTag = \"h:sub\", elementAttrs = [], elementChildren = []}"
+    err2 = "templates-nscall/_invalid.tpl: No splice bound for h:invalid\nBound splices: h:call h:main h:main2\nNode: Element {elementTag = \"h:invalid\", elementAttrs = [], elementChildren = []}"
 
 
 ------------------------------------------------------------------------------
@@ -357,7 +357,7 @@
     H.assertEqual "exceptions" (Right (msg, err)) $ res
 
   where
-    msg = "templates-loaderror/_error.tpl: Exception in splice compile: Prelude.read: no parse\n   ... via templates-loaderror/_error.tpl: h:adder\n   ... via templates-loaderror/test.tpl: h:call2\nBound splices: h:adder h:call2 h:call1\nNode: Element {elementTag = \"h:adder\", elementAttrs = [(\"value\",\"noparse\")], elementChildren = []}"
+    msg = "templates-loaderror/_error.tpl: Exception in splice compile: Prelude.read: no parse\n   ... via templates-loaderror/_error.tpl: h:adder\n   ... via templates-loaderror/test.tpl: h:call2\nBound splices: h:adder h:call1 h:call2\nNode: Element {elementTag = \"h:adder\", elementAttrs = [(\"value\",\"noparse\")], elementChildren = []}"
     err = SpliceError [ ( ["test"]
                         , Just "templates-loaderror/_error.tpl"
                         , "h:adder"),
@@ -365,7 +365,7 @@
                         , Just "templates-loaderror/test.tpl"
                         ,"h:call2") ]
               (Just "templates-loaderror/_error.tpl")
-              ["h:adder", "h:call2", "h:call1"]
+              ["h:adder", "h:call1", "h:call2"]
               (X.Element "h:adder" [("value", "noparse")] [])
               "Exception in splice compile: Prelude.read: no parse"
     hc = HeistConfig sc "h" True
