diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Changelog
 
+## Unreleased
+### [Removed]
+- Support for GHC 8.8, 8.10 and 9.0. The minimum supported version is now GHC 9.2.
+
+## 0.1.9
+- [#54](https://github.com/jonascarpay/calligraphy/pull/54) Compatibility with GHC 9.12
+- [#56](https://github.com/jonascarpay/calligraphy/pull/56) Compatibility with GHC 9.12
+
 ## 0.1.8
 ### [Changed]
 - [#49] Make the background of modules tinted.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
 `calligraphy` is a Haskell call graph/source code visualizer.
 
 It works directly on GHC-generated HIE files, giving us features that would otherwise be tricky, like type information and support for generated files.
-`calligraphy` has been tested with all versions of GHC that produce HIE files (i.e. GHC 8.8 through 9.6.)
+`calligraphy` supports GHC 9.2 and later.
 
 See [the accompanying blog post](https://jonascarpay.com/posts/2022-04-26-calligraphy-tutorial.html) for more examples, and an extended tutorial.
 
diff --git a/calligraphy.cabal b/calligraphy.cabal
--- a/calligraphy.cabal
+++ b/calligraphy.cabal
@@ -1,6 +1,6 @@
-cabal-version:   2.4
+cabal-version:   3.0
 name:            calligraphy
-version:         0.1.8
+version:         0.1.9
 license:         BSD-3-Clause
 build-type:      Simple
 license-file:    LICENSE
@@ -8,14 +8,13 @@
 maintainer:      Jonas Carpay <jonascarpay@gmail.com>
 copyright:       2022 Jonas Carpay
 tested-with:
-  GHC ==8.8.4
-   || ==8.10.7
-   || ==9.0.2
-   || ==9.2.8
+  GHC ==9.2.8
    || ==9.4.8
    || ==9.6.6
    || ==9.8.4
    || ==9.10.1
+   || ==9.12.4
+   || ==9.14.1
 
 extra-doc-files:
   CHANGELOG.md
@@ -25,7 +24,7 @@
 description:
   Calligraphy is a Haskell call graph/source code visualizer.
   It works directly on GHC-generated HIE files, giving us features that would otherwise be tricky, like type information and support for generated files.
-  Calligraphy has been tested with all versions of GHC that produce HIE files (i.e. GHC 8.8 through 9.6.)
+  Calligraphy supports GHC 9.2 and later.
   See the project's github page for more information.
 
 homepage:        https://github.com/jonascarpay/calligraphy#readme
@@ -33,10 +32,10 @@
 
 source-repository head
   type:     git
-  location: git://github.com/jonascarpay/calligraphy
+  location: https://github.com/jonascarpay/calligraphy
 
 common common-options
-  build-depends:    base >=4.9 && <5
+  build-depends:    base >=4.16 && <5
   default-language: Haskell2010
   ghc-options:
     -Wall -Wcompat -Widentities -Wincomplete-uni-patterns
diff --git a/src/Calligraphy/Compat/Debug.hs b/src/Calligraphy/Compat/Debug.hs
--- a/src/Calligraphy/Compat/Debug.hs
+++ b/src/Calligraphy/Compat/Debug.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE CPP #-}
-
 -- | Debug tools for GHC-related data
 module Calligraphy.Compat.Debug
   ( ppHieFile,
@@ -12,7 +10,6 @@
 import Calligraphy.Util.Printer
 import qualified Data.Map as Map
 
-#if MIN_VERSION_ghc(9,2,0)
 import qualified GHC.Data.FastString as GHC
 import qualified GHC.Iface.Ext.Types as GHC
 import qualified GHC.Types.Name as GHC
@@ -20,25 +17,9 @@
 import qualified GHC.Types.Unique as GHC
 import qualified GHC.Unit as GHC
 import qualified GHC.Utils.Outputable as GHC
-#elif MIN_VERSION_ghc(9,0,0)
-import qualified GHC.Data.FastString as GHC
-import qualified GHC.Iface.Ext.Types as GHC
-import qualified GHC.Types.Name as GHC
-import qualified GHC.Types.SrcLoc as GHC
-import qualified GHC.Types.Unique as GHC
-import qualified GHC.Unit as GHC
-import qualified GHC.Utils.Outputable as GHC
-import qualified GHC.Driver.Session as GHC
-#else
-import qualified HieTypes as GHC
-import qualified Module as GHC
-import qualified FastString as GHC
-import qualified GhcPlugins as GHC
-import qualified Unique as GHC
-#endif
 
 ppHieFile :: Prints GHC.HieFile
-ppHieFile (GHC.HieFile path (GHC.Module _ mdl) _types (GHC.HieASTs asts) _exps _src) = do
+ppHieFile GHC.HieFile{hie_hs_file=path, hie_module=GHC.Module _ mdl, hie_asts=GHC.HieASTs asts} = do
   strLn "Hie File"
   indent $ do
     strLn "path:"
@@ -47,16 +28,11 @@
     indent $ strLn (GHC.moduleNameString mdl)
     strLn "contents:"
     indent $
-#if MIN_VERSION_ghc(9,2,0)
       forM_ (Map.toList asts) $ \(GHC.LexicalFastString hiePath, ast) -> do
-#else
-      forM_ (Map.toList asts) $ \(hiePath, ast) -> do
-#endif
         strLn (GHC.unpackFS hiePath)
         indent $ ppAst ast
 
 ppAst :: GHC.HieAST a -> Printer ()
-#if MIN_VERSION_ghc(9,2,0)
 ppAst (GHC.Node (GHC.SourcedNodeInfo nodeInfo) spn children) = do
   strLn (showSpan spn)
   forM_ (Map.toList nodeInfo) $ \(origin, GHC.NodeInfo anns _ ids) -> do
@@ -69,24 +45,6 @@
         indent $ forM_ idnDetails $ strLn . GHC.showSDocOneLine GHC.defaultSDocContext . GHC.ppr
       forM_ anns $ \(GHC.NodeAnnotation constr typ) -> strLn (show (constr, typ))
   indent $ mapM_ ppAst children
-#elif MIN_VERSION_ghc(9,0,0)
-ppAst (GHC.Node (GHC.SourcedNodeInfo nodeInfo) spn children) = do
-  strLn (showSpan spn)
-  forM_ nodeInfo $ \ (GHC.NodeInfo anns _ ids) -> do
-    forM_ (Map.toList ids) $ \(idn, GHC.IdentifierDetails _ idnDetails) -> do
-      ppIdentifier idn
-      indent $ forM_ idnDetails $ strLn . GHC.showSDocOneLine (GHC.initSDocContext GHC.unsafeGlobalDynFlags GHC.defaultUserStyle) . GHC.ppr
-    forM_ anns $ showLn
-  indent $ mapM_ ppAst children
-#else
-ppAst (GHC.Node (GHC.NodeInfo anns _ ids) spn children) = do
-  strLn (showSpan spn)
-  forM_ (Map.toList ids) $ \(idn, GHC.IdentifierDetails _ idnDetails) -> do
-    ppIdentifier idn
-    indent $ forM_ idnDetails showLn
-  mapM_ showLn anns
-  indent $ mapM_ ppAst children
-#endif
 
 showSpan :: GHC.RealSrcSpan -> String
 showSpan s =
diff --git a/src/Calligraphy/Compat/GHC.hs b/src/Calligraphy/Compat/GHC.hs
--- a/src/Calligraphy/Compat/GHC.hs
+++ b/src/Calligraphy/Compat/GHC.hs
@@ -32,6 +32,9 @@
     mkSplitUniqSupply,
     moduleName,
     moduleNameString,
+#if MIN_VERSION_ghc(9,14,0)
+    newNameCache,
+#endif
     nameUnique,
     realSrcSpanEnd,
     realSrcSpanStart,
@@ -48,26 +51,13 @@
 
 #if MIN_VERSION_ghc(9,6,0)
 import Language.Haskell.Syntax.Module.Name (moduleNameString, ModuleName)
-#elif MIN_VERSION_ghc(9,0,0)
+#else
 import GHC.Unit.Module.Name (moduleNameString, ModuleName)
 #endif
 
-#if MIN_VERSION_ghc(9,0,0)
 import GHC.Iface.Type
 import GHC.Types.Avail
 import GHC.Types.Name
 import GHC.Types.Unique
 import GHC.Types.Unique.Supply
 import GHC.Unit.Types
-#else
-import Avail
-import GHC
-import HieBin
-import HieTypes
-import IfaceType
-import Name
-import NameCache
-import SrcLoc
-import UniqSupply
-import Unique
-#endif
diff --git a/src/Calligraphy/Compat/Lib.hs b/src/Calligraphy/Compat/Lib.hs
--- a/src/Calligraphy/Compat/Lib.hs
+++ b/src/Calligraphy/Compat/Lib.hs
@@ -25,10 +25,17 @@
 import qualified Data.Map as Map
 import qualified Data.Set as Set
 
-#if MIN_VERSION_ghc(9,4,0)
+#if MIN_VERSION_ghc(9,14,0)
 
 getHieFiles :: [FilePath] -> IO [HieFile]
 getHieFiles filePaths = do
+  ref <- newIORef =<< GHC.newNameCache
+  forM filePaths (readHieFileWithWarning ref)
+
+#elif MIN_VERSION_ghc(9,4,0)
+
+getHieFiles :: [FilePath] -> IO [HieFile]
+getHieFiles filePaths = do
   ref <- newIORef =<< GHC.initNameCache 'z' []
   forM filePaths (readHieFileWithWarning ref)
 
@@ -67,7 +74,7 @@
   nameCache <- readIORef ref
   readHieFile nameCache path
 
-#elif MIN_VERSION_ghc(9,0,0)
+#else
 
 sourceInfo f (Node (SourcedNodeInfo inf) sp children) = (\inf' -> Node (SourcedNodeInfo inf') sp children) <$> Map.alterF (maybe (pure Nothing) (fmap Just . f)) SourceInfo inf
 
@@ -75,18 +82,6 @@
 
 readHieFileCompat ref = readHieFile (NCU (atomicModifyIORef ref))
 
-#else
-
-sourceInfo f (Node inf sp children) = (\inf' -> Node inf' sp children) <$> f inf
-
-showContextInfo = show
-
-readHieFileCompat ref fp = do
-  cache <- readIORef ref
-  (res, cache') <- readHieFile cache fp
-  writeIORef ref cache'
-  pure res
-
 #endif
 
 isInstanceNode :: NodeInfo a -> Bool
@@ -95,7 +90,6 @@
 isMinimalNode :: NodeInfo a -> Bool
 isDerivingNode :: NodeInfo a -> Bool
 showAnns :: NodeInfo a -> String
-#if MIN_VERSION_ghc(9,2,0)
 
 isInstanceNode (NodeInfo anns _ _) = any (flip Set.member anns) [NodeAnnotation "ClsInstD" "InstDecl", NodeAnnotation "DerivDecl" "DerivDecl"]
 
@@ -110,22 +104,6 @@
 showAnns (NodeInfo anns _ _) = unwords (show . unNodeAnnotation <$> Set.toList anns)
   where
     unNodeAnnotation (NodeAnnotation a b) = (a, b)
-
-#else
-
-isInstanceNode (NodeInfo anns _ _) = any (flip Set.member anns) [("ClsInstD", "InstDecl"), ("DerivDecl", "DerivDecl")]
-
-isTypeSignatureNode (NodeInfo anns _ _) = Set.member ("TypeSig", "Sig") anns
-
-isInlineNode (NodeInfo anns _ _) = Set.member ("InlineSig", "Sig") anns
-
-isMinimalNode (NodeInfo anns _ _) = Set.member ("MinimalSig", "Sig") anns
-
-isDerivingNode (NodeInfo anns _ _) = Set.member ("HsDerivingClause", "HsDerivingClause") anns
-
-showAnns (NodeInfo anns _ _) = unwords (show <$> Set.toList anns)
-
-#endif
 
 mergeSpans :: Span -> Span -> Span
 mergeSpans sp1 sp2 =
diff --git a/src/Calligraphy/Phases/Parse.hs b/src/Calligraphy/Phases/Parse.hs
--- a/src/Calligraphy/Phases/Parse.hs
+++ b/src/Calligraphy/Phases/Parse.hs
@@ -138,7 +138,7 @@
        in (ParsePhaseDebugInfo debugs, CallGraph mods (rekeyCalls keymap (mconcat calls)) typeEdges)
 
 parseHieFile :: GHC.HieFile -> HieParse ParsedFile
-parseHieFile file@(GHC.HieFile filepath mdl _ _ avails _) = do
+parseHieFile file@GHC.HieFile{hie_hs_file=filepath,hie_module=mdl, hie_exports=avails} = do
   lextree <- either (throwError . TreeError modname filepath) pure $ structure decls
   let calls = resolveCalls (fmap (EnumSet.findMin . rdKeys) lextree)
   forest <- forestT (mkDecl exportKeys) (mkForest lextree)
@@ -205,7 +205,7 @@
 
 -- | Collect declarations, uses, and types in a HIE file
 collect :: GHC.HieFile -> Collect
-collect (GHC.HieFile _ _ typeArr (GHC.HieASTs asts) _ _) = execState (forT_ traverse asts go) (Collect mempty mempty mempty)
+collect GHC.HieFile{hie_types=typeArr, hie_asts=GHC.HieASTs asts} = execState (forT_ traverse asts go) (Collect mempty mempty mempty)
   where
     tellDecl :: GHC.Name -> DeclType -> GHC.RealSrcSpan -> State Collect ()
     tellDecl nm typ spn = modify $ \(Collect decls uses types) -> Collect (decl : decls) uses types
diff --git a/src/Calligraphy/Prelude.hs b/src/Calligraphy/Prelude.hs
--- a/src/Calligraphy/Prelude.hs
+++ b/src/Calligraphy/Prelude.hs
@@ -1,22 +1,14 @@
-{-# LANGUAGE CPP #-}
 module Calligraphy.Prelude
   ( module Control.Monad
   , module Data.Either
   , module Data.Foldable
   , module Data.List
   , module Data.Monoid
-#if MIN_VERSION_ghc(9,0,0)
   , module GHC.Iface.Ext.Binary
   , module GHC.Iface.Ext.Types
   , module GHC.Types.Name.Cache
   , module GHC.Types.SrcLoc
   , module GHC.Utils.Outputable
-#else
-  , module HieBin
-  , module HieTypes
-  , module NameCache
-  , module SrcLoc
-#endif
   ) where
 
 import Control.Monad
@@ -24,15 +16,8 @@
 import Data.Foldable hiding (toList)
 import Data.List (last, (++), replicate, zip, filter, isPrefixOf)
 import Data.Monoid (Monoid, mempty, mconcat, mappend, Ap(..))
-#if MIN_VERSION_ghc(9,0,0)
 import GHC.Iface.Ext.Binary
 import GHC.Iface.Ext.Types
 import GHC.Types.Name.Cache
 import GHC.Types.SrcLoc
 import GHC.Utils.Outputable (ppr, showSDocUnsafe)
-#else
-import HieBin
-import HieTypes
-import NameCache
-import SrcLoc
-#endif
