diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,15 @@
 CHANGELOG
 =========
 
+Version 0.2.4.0
+---------------
+
+*January 17, 2020*
+
+<https://github.com/mstksg/hakyll-dhall/releases/tag/v0.2.4.0>
+
+*   Compatibility with *dhall-1.29*, dropping support for previous dhalls.
+
 Version 0.2.3.0
 ---------------
 
diff --git a/app/test-app.hs b/app/test-app.hs
--- a/app/test-app.hs
+++ b/app/test-app.hs
@@ -14,5 +14,5 @@
       route idRoute
       compile $ parseDhall
                   Nothing
-                  (auto :: Type String)
+                  (auto :: Decoder String)
                   "./test-dhall/parse-test.dhall"
diff --git a/hakyll-dhall.cabal b/hakyll-dhall.cabal
--- a/hakyll-dhall.cabal
+++ b/hakyll-dhall.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.31.1.
+-- This file has been generated from package.yaml by hpack version 0.31.2.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 527273a80edbd480ea9814bed3eef0477743d6d989902d5e6a22547b01dfe821
+-- hash: 8217e2fc7df098b437688872bf86eb4566e4405b3e3f40efa69661d9cd2c3c49
 
 name:           hakyll-dhall
-version:        0.2.3.0
+version:        0.2.4.0
 synopsis:       Dhall compiler for Hakyll
 description:    Hakyll compiler and loader for Dhall files.  Functions are intended to track
                 all local dependencies within the project directory, so rebuilds are
@@ -24,7 +24,7 @@
 copyright:      (c) Justin Le 2018
 license:        BSD3
 license-file:   LICENSE
-tested-with:    GHC >= 8.2 && < 8.8
+tested-with:    GHC >= 8.4
 build-type:     Simple
 extra-source-files:
     README.md
@@ -50,13 +50,13 @@
   build-depends:
       base >=4.7 && <5
     , binary
-    , cborg
     , containers
     , data-default-class
-    , dhall >=1.22
+    , dhall >=1.29
     , filepath
     , hakyll >=4.10
-    , lens-family-core
+    , microlens
+    , microlens-th
     , mtl
     , prettyprinter
     , text
@@ -72,7 +72,7 @@
   ghc-options: -Wall -Wcompat -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
   build-depends:
       base >=4.7 && <5
-    , dhall >=1.22
+    , dhall >=1.29
     , hakyll >=4.10
     , hakyll-dhall
   default-language: Haskell2010
diff --git a/src/Hakyll/Web/Dhall.hs b/src/Hakyll/Web/Dhall.hs
--- a/src/Hakyll/Web/Dhall.hs
+++ b/src/Hakyll/Web/Dhall.hs
@@ -1,13 +1,17 @@
 {-# LANGUAGE AllowAmbiguousTypes #-}
 {-# LANGUAGE ConstraintKinds     #-}
+{-# LANGUAGE DataKinds           #-}
 {-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE DeriveGeneric       #-}
+{-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE GADTs               #-}
 {-# LANGUAGE KindSignatures      #-}
+{-# LANGUAGE NamedFieldPuns      #-}
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE RankNTypes          #-}
 {-# LANGUAGE RecordWildCards     #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
 {-# LANGUAGE TupleSections       #-}
 {-# LANGUAGE TypeApplications    #-}
 
@@ -70,13 +74,13 @@
 
 import           Control.Monad
 import           Control.Monad.Error.Class
-import           Control.Monad.IO.Class
 import           Control.Monad.Trans.State.Strict
 import           Data.Default.Class
-import           Data.IORef
+import           Data.Kind
 import           Data.Maybe                            as M
 import           Data.Typeable                         (Typeable)
-import           Dhall
+import           Data.Void
+import           Dhall hiding                          (map)
 import           Dhall.Binary
 import           Dhall.Core
 import           Dhall.Diff
@@ -91,20 +95,18 @@
 import           Hakyll.Core.Identifier
 import           Hakyll.Core.Item
 import           Hakyll.Core.Writable
-import           Lens.Family                           (LensLike, LensLike', (.~), (&))
+import           Lens.Micro
+import           Lens.Micro.TH
 import           System.FilePath
 import           System.IO
-import qualified Codec.CBOR.Read                       as CBOR
-import qualified Codec.CBOR.Term                       as CBOR
-import qualified Codec.CBOR.Write                      as CBOR
 import qualified Data.Binary                           as Bi
 import qualified Data.Binary.Get                       as Bi
 import qualified Data.Binary.Put                       as Bi
-import qualified Data.Kind                             as K
 import qualified Data.Set                              as S
 import qualified Data.Text                             as T
 import qualified Data.Text.Prettyprint.Doc             as PP
 import qualified Data.Text.Prettyprint.Doc.Render.Text as PP
+import qualified Dhall.Map                             as DM
 
 -- | Newtype wrapper over @'Expr' 'Src' a@ (A Dhall expression) with an
 -- appropriate 'Bi.Binary' instance, meant to be usable as a compilable
@@ -112,18 +114,11 @@
 newtype DExpr a = DExpr { getDExpr :: Expr Src a }
     deriving (Generic, Typeable)
 
-instance (PP.Pretty a, ToTerm a, FromTerm a) => Bi.Binary (DExpr a) where
-    put = Bi.putBuilder
-        . CBOR.toBuilder
-        . CBOR.encodeTerm
-        . encode
-        . getDExpr
+instance Bi.Binary (DExpr Void) where
+    put = Bi.putLazyByteString . encodeExpression . denote . vacuous . getDExpr
     get = do
         bs     <- Bi.getRemainingLazyByteString
-        (_, t) <- either (fail . show) pure $
-                    CBOR.deserialiseFromBytes CBOR.decodeTerm bs
-        M.maybe (fail "dhall decode failure") (pure . DExpr) $
-            decode t
+        either (fail . show) (pure . DExpr . denote @Void) $ decodeExpression bs
 
 -- | Automatically "pretty prints" in multi-line form.  For more
 -- fine-grained results, see 'dhallPrettyCompilerWith' and family.
@@ -172,24 +167,6 @@
     }
   deriving (Generic, Typeable)
 
--- | Lens for '_dcoResolver' field of 'DhallCompilerOptions'.
-dcoResolver
-    :: Functor f
-    => LensLike f (DhallCompilerOptions a) (DhallCompilerOptions b) (DhallResolver a) (DhallResolver b)
-dcoResolver f (DCO r m n) = (\r' -> DCO r' m n) <$> f r
-
--- | Lens for '_dcoMinimize' field of 'DhallCompilerOptions'.
-dcoMinimize
-    :: Functor f
-    => LensLike' f (DhallCompilerOptions a) Bool
-dcoMinimize f (DCO r m n) = (\m' -> DCO r m' n) <$> f m
-
--- | Lens for '_dcoNormalize' field of 'DhallCompilerOptions'.
-dcoNormalize
-    :: Functor f
-    => LensLike' f (DhallCompilerOptions a) Bool
-dcoNormalize f (DCO r m n) = DCO r m <$> f n
-
 -- | Method for resolving imports.
 --
 -- The choice will determine the type of expression that 'loadDhallExpr'
@@ -200,7 +177,7 @@
 -- none of them. Hopefully one day this library will offer the ability to
 -- resolve only certain types of imports (environment variables, absolute
 -- paths) and not others (remote network, local paths).
-data DhallResolver :: K.Type -> K.Type where
+data DhallResolver :: Type -> Type where
     -- | Leave imports as imports, but optionally remap the destinations.
     DRRaw  :: { _drRemap :: Import -> Compiler (Expr Src Import)
                 -- ^ Optionally remap the destinations.
@@ -224,26 +201,26 @@
                 -- That is, do not trust any dependencies on the local disk
                 -- outside of the project directory, but trust that any URL
                 -- imports remain unchanged.
-              } -> DhallResolver X
+              } -> DhallResolver Void
 
 -- | Lens for '_drRemap' field of 'DhallResolver'.
 drRemap
-    :: Functor f
-    => LensLike' f (DhallResolver Import) (Import -> Compiler (Expr Src Import))
+    :: Lens' (DhallResolver Import) (Import -> Compiler (Expr Src Import))
 drRemap f (DRRaw r) = DRRaw <$> f r
 
 -- | Lens for '_drFull' field of 'DhallResolver'.
 drFull
-    :: Functor f
-    => LensLike' f (DhallResolver X) (S.Set DhallCompilerTrust)
+    :: Lens' (DhallResolver Void) (S.Set DhallCompilerTrust)
 drFull f (DRFull t) = DRFull <$> f t
 
+makeLenses ''DhallCompilerOptions
+
 -- | Default 'DhallCompilerOptions'.  If the type variable is not
 -- inferrable, it can be helpful to use /TypeApplications/ syntax:
 --
 -- @
 -- 'defaultDhallCompilerOptions' \@'Import'     -- do not resolve imports
--- 'defaultDhallCompilerOptions' \@'X'          -- resolve imports
+-- 'defaultDhallCompilerOptions' \@'Void'          -- resolve imports
 -- @
 --
 -- Default values are:
@@ -278,7 +255,7 @@
 -- | Only trust remote imports remain unchanged.  Rebuild every time if any
 -- absolute, home-directory-based, or environment variable imports are in
 -- file.
-instance DefaultDhallResolver X where
+instance DefaultDhallResolver Void where
     defaultDhallResolver = DRFull $ S.singleton DCTRemote
 
 -- | @'def' = 'defaultDhallCompilerOptions'@
@@ -296,7 +273,7 @@
 --
 -- @
 -- 'dhallRawPrettyCompiler'  = 'dhallPrettyCompiler' \@'Import'
--- 'dhallFullPrettyCompiler' = 'dhallPrettyCompiler' \@'X'
+-- 'dhallFullPrettyCompiler' = 'dhallPrettyCompiler' \@'Void'
 -- @
 --
 -- It might be more convenient to just use 'dhallRawCompiler' or
@@ -321,7 +298,7 @@
 -- dependencies.  Essentially a Dhall pretty-printer, (optional)
 -- normalizer, and re-formatter.
 dhallFullPrettyCompiler :: Compiler (Item String)
-dhallFullPrettyCompiler = dhallPrettyCompilerWith @X defaultDhallCompilerOptions
+dhallFullPrettyCompiler = dhallPrettyCompilerWith @Void defaultDhallCompilerOptions
 
 -- | 'dhallPrettyCompiler', but with custom 'DhallCompilerOptions'.
 dhallPrettyCompilerWith
@@ -368,7 +345,7 @@
 -- @
 -- 'match' "config/**.dhall" $ do
 --     'route' 'mempty'
---     'compile' $ 'dExprCompiler' \@'X'
+--     'compile' $ 'dExprCompiler' \@'Void'
 -- @
 --
 -- This will save all of the dhall files in the directory ./config in the
@@ -408,14 +385,14 @@
 -- interpret it as a value of the given type.  Tracks all dependencies, so
 -- will trigger rebuilds based on downstream changes.
 dhallCompiler
-    :: Type a
+    :: Decoder a
     -> Compiler (Item a)
 dhallCompiler = dhallCompilerWith defaultDhallCompilerOptions
 
 -- | 'dhallCompiler', but with custom 'DhallCompilerOptions'.
 dhallCompilerWith
-    :: DhallCompilerOptions X
-    -> Type a
+    :: DhallCompilerOptions Void
+    -> Decoder a
     -> Compiler (Item a)
 dhallCompilerWith dco t = do
     DExpr e <- itemBody <$> dExprCompilerWith dco
@@ -424,14 +401,14 @@
 -- | Wrapper over 'load' and 'interpretDhallCompiler'.  Pulls up a 'DExpr'
 -- compiled or saved into the Hakyll cache and interprets it as a value.
 --
--- Expects item at identifier to be saved as @'DExpr' 'X'@ (possibly using
--- @'dExprCompiler' \@'X'@)
+-- Expects item at identifier to be saved as @'DExpr' 'Void'@ (possibly using
+-- @'dExprCompiler' \@'Void'@)
 --
 -- Tracks dependencies properly, so any pages or routes that use the saved
 -- Dhall expression will re-build if any of the downstream Dhall files are
 -- edited.
 loadDhall
-    :: Type a
+    :: Decoder a
     -> Identifier
     -> Compiler (Item a)
 loadDhall t i = do
@@ -442,14 +419,14 @@
 -- a 'DExpr' saved into the Hakyll cache as a snapshot and interprets it as
 -- a value.
 --
--- Expects item at identifier to be saved as @'DExpr' 'X'@ (possibly using
--- @'dExprCompiler' \@'X'@)
+-- Expects item at identifier to be saved as @'DExpr' 'Void'@ (possibly using
+-- @'dExprCompiler' \@'Void'@)
 --
 -- Tracks dependencies properly, so any pages or routes that use the saved
 -- Dhall expression will re-build if any of the downstream Dhall files are
 -- edited.
 loadDhallSnapshot
-    :: Type a
+    :: Decoder a
     -> Identifier
     -> Snapshot
     -> Compiler (Item a)
@@ -472,16 +449,16 @@
 -- To directly obtain a Dhall expression, see 'parseDhallExpr'.
 parseDhall
     :: Maybe FilePath                   -- ^ Override directory root
-    -> Type a
+    -> Decoder a
     -> T.Text
     -> Compiler (Item a)
 parseDhall = parseDhallWith defaultDhallCompilerOptions
 
 -- | Version of 'parseDhall' taking custom 'DhallCompilerOptions'.
 parseDhallWith
-    :: DhallCompilerOptions X
+    :: DhallCompilerOptions Void
     -> Maybe FilePath                   -- ^ Override directory root
-    -> Type a
+    -> Decoder a
     -> T.Text
     -> Compiler (Item a)
 parseDhallWith dco fp t b = do
@@ -489,11 +466,11 @@
     makeItem =<< interpretDhallCompiler t e
 
 -- | Interpret a fully resolved Dhall expression as a value of a type,
--- given a 'Type'. Run in 'Compiler' to integrate error handling with
--- Hakyll.
+-- given a 'Decoder'.  You can use this to integrate error handling with
+-- Hakyll, since it is run in a 'Compiler'.
 interpretDhallCompiler
-    :: Type a
-    -> Expr Src X
+    :: Decoder a
+    -> Expr Src Void
     -> Compiler a
 interpretDhallCompiler t e = case rawInput t e of
     Nothing -> throwError . (terr:) . (:[]) $ case typeOf e of
@@ -501,6 +478,7 @@
       Right t0  -> T.unpack
                  . PP.renderStrict
                  . PP.layoutSmart layoutOpts
+                 . doc
                  . diffNormalized (expected t)
                  $ t0
     Just x  -> pure x
@@ -547,8 +525,11 @@
     -> Compiler (Expr Src Import)
 parseRawDhallExprWith DCO{..} b =
     case exprFromText "Hakyll.Web.Dhall.parseRawDhallExprWith" b of
-      Left  e -> throwError . (:[]) $
-        "Error parsing raw dhall file: " ++ show e
+      Left  e -> throwError
+        [ "Error parsing raw dhall file"
+        , "<<" ++ T.unpack b ++ ">>"
+        , show e
+        ]
       Right e -> join <$> traverse (_drRemap _dcoResolver) e
 
 -- | Resolve all imports in a parsed Dhall expression.
@@ -558,20 +539,15 @@
 -- Hakyll, and so modifications to required files will also cause upstream
 -- files to be rebuilt.
 resolveDhallImports
-    :: DhallCompilerOptions X
+    :: DhallCompilerOptions Void
     -> Maybe FilePath                   -- ^ Override directory root
     -> Expr Src Import
-    -> Compiler (Expr Src X)
+    -> Compiler (Expr Src Void)
 resolveDhallImports DCO{..} d e = do
-    (res, imps) <- unsafeCompiler $ do
-      iRef <- newIORef []
-      res <- evalStateT (loadWith e) $
-        emptyStatus (fromMaybe "./" d)
-          & resolver .~ \i -> do
-              liftIO $ modifyIORef iRef (i:)
-              exprFromImport i
-      (res,) <$> readIORef iRef
-    compilerTellDependencies $ mapMaybe mkDep imps
+    (res, Status{_cache}) <- unsafeCompiler $
+        runStateT (loadWith e) (emptyStatus (fromMaybe "./" d))
+    let imps = mapMaybe (mkDep . chainedImport) (DM.keys _cache)
+    compilerTellDependencies imps
     pure res
   where
     DRFull{..} = _dcoResolver
diff --git a/test-dhall/foo.dhall b/test-dhall/foo.dhall
--- a/test-dhall/foo.dhall
+++ b/test-dhall/foo.dhall
@@ -1,3 +1,1 @@
-[ ./test1.dhall
-, ./test2.dhall
-]
+[ ./test1.dhall, ./test2.dhall ]
diff --git a/test-dhall/test-file.dhall b/test-dhall/test-file.dhall
--- a/test-dhall/test-file.dhall
+++ b/test-dhall/test-file.dhall
@@ -1,6 +1,12 @@
-{ foo = ./foo.dhall
-, bar = < Hey = {=} | Ho : {} >
-, baz = let not = https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not
-        in  not True
-, hi  = ~/local/local-test.dhall
+{ foo =
+    ./foo.dhall
+, bar =
+    < Hey | Ho >.Hey
+, baz =
+    let not =
+          https://raw.githubusercontent.com/dhall-lang/Prelude/35deff0d41f2bf86c42089c6ca16665537f54d75/Bool/not sha256:723df402df24377d8a853afed08d9d69a0a6d86e2e5b2bac8960b0d4756c7dc4
+
+    in  not True
+, hi =
+    ~/local/local-test.dhall
 }
