diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+# [0.2.0.0](https://github.com/haskell-nix/hnix-store/compare/readonly-0.1.0.0...readonly-0.2.0.0) 2026-10-21
+
+Remove duplicate code from `hnix-store-readonly`
+
+`References`, `makeStorePath`, `makeFixedOutputPath`, and `makeType`
+already exist in `System.Nix.StorePath.ContentAddressed` (added in
+cf6c416) but were never removed from `System.Nix.Store.ReadOnly`.
+
+- Remove the redundant definitions from `hnix-store-readonly`
+- Move tests for `makeStorePath`/`makeFixedOutputPath` to
+  `hnix-store-core` where the code now lives
+- Remove unused dependencies from `hnix-store-readonly`
+
 # 0.1.0.0 2024-07-31
 
 * Initial release
diff --git a/hnix-store-readonly.cabal b/hnix-store-readonly.cabal
--- a/hnix-store-readonly.cabal
+++ b/hnix-store-readonly.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.2
 name:                hnix-store-readonly
-version:             0.1.0.0
+version:             0.2.0.0
 synopsis:            Read-only Nix store
 description:
   Path computation without interaction with the actual Nix store
@@ -22,6 +22,7 @@
   default-extensions:
       Rank2Types
     , ScopedTypeVariables
+    , ImportQualifiedPost
     , TypeApplications
   default-language: Haskell2010
 
@@ -35,9 +36,8 @@
     , hnix-store-nar >= 0.1
     , bytestring
     , crypton
+    , dependent-sum > 0.7
     , mtl
-    , text
-    , unordered-containers
   hs-source-dirs:      src
 
 test-suite readonly
@@ -51,11 +51,5 @@
   build-tool-depends:
     hspec-discover:hspec-discover
   build-depends:
-      base
-    , hnix-store-core
-    , hnix-store-readonly
-    , bytestring
-    , crypton
-    , data-default-class
+      base >=4.12 && <5
     , hspec
-    , unordered-containers
diff --git a/src/System/Nix/Store/ReadOnly.hs b/src/System/Nix/Store/ReadOnly.hs
--- a/src/System/Nix/Store/ReadOnly.hs
+++ b/src/System/Nix/Store/ReadOnly.hs
@@ -1,117 +1,37 @@
+{-# LANGUAGE GADTs #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module System.Nix.Store.ReadOnly
-  ( makeStorePath
-  , makeTextPath
-  , makeFixedOutputPath
-  , computeStorePathForText
-  , computeStorePathForPath
+  ( computeStorePathForPath
   ) where
 
 import Control.Monad.State (StateT, execStateT, modify)
 import Crypto.Hash (Context, Digest, SHA256)
 import Data.ByteString (ByteString)
-import Data.HashSet (HashSet)
-import System.Nix.Hash (BaseEncoding(Base16), NamedAlgo(algoName))
-import System.Nix.Store.Types (FileIngestionMethod(..), PathFilter, RepairMode)
+import Data.Dependent.Sum (DSum((:=>)))
+import System.Nix.StorePath.ContentAddressed
+import System.Nix.ContentAddress (ContentAddressMethod (..))
+import System.Nix.Hash (HashAlgo(..))
+import System.Nix.Store.Types (PathFilter, RepairMode)
 import System.Nix.StorePath (StoreDir, StorePath, StorePathName)
 
-import qualified Crypto.Hash
-import qualified Data.ByteString.Char8
-import qualified Data.ByteString
-import qualified Data.HashSet
-import qualified Data.List
-import qualified Data.Text
-import qualified Data.Text.Encoding
-import qualified System.Nix.Hash
-import qualified System.Nix.Nar
-import qualified System.Nix.StorePath
-
-makeStorePath
-  :: forall hashAlgo
-   . (NamedAlgo hashAlgo)
-  => StoreDir
-  -> ByteString
-  -> Digest hashAlgo
-  -> StorePathName
-  -> StorePath
-makeStorePath storeDir ty h nm =
- System.Nix.StorePath.unsafeMakeStorePath storeHash nm
- where
-  storeHash = System.Nix.StorePath.mkStorePathHashPart @hashAlgo s
-  s =
-    Data.ByteString.intercalate ":" $
-      ty:fmap Data.Text.Encoding.encodeUtf8
-        [ algoName @hashAlgo
-        , System.Nix.Hash.encodeDigestWith Base16 h
-        , Data.Text.pack . Data.ByteString.Char8.unpack $ System.Nix.StorePath.unStoreDir storeDir
-        , System.Nix.StorePath.unStorePathName nm
-        ]
-
-makeTextPath
-  :: StoreDir
-  -> StorePathName
-  -> Digest SHA256
-  -> HashSet StorePath
-  -> StorePath
-makeTextPath storeDir nm h refs = makeStorePath storeDir ty h nm
- where
-  ty =
-    Data.ByteString.intercalate
-      ":"
-      $ "text"
-      : Data.List.sort
-          (System.Nix.StorePath.storePathToRawFilePath storeDir
-           <$> Data.HashSet.toList refs)
-
-makeFixedOutputPath
-  :: forall hashAlgo
-  .  NamedAlgo hashAlgo
-  => StoreDir
-  -> FileIngestionMethod
-  -> Digest hashAlgo
-  -> StorePathName
-  -> StorePath
-makeFixedOutputPath storeDir recursive h =
-  if recursive == FileIngestionMethod_FileRecursive
-     && (algoName @hashAlgo) == "sha256"
-  then makeStorePath storeDir "source" h
-  else makeStorePath storeDir "output:out" h'
- where
-  h' =
-    Crypto.Hash.hash @ByteString @SHA256
-      $  "fixed:out:"
-      <> Data.Text.Encoding.encodeUtf8 (algoName @hashAlgo)
-      <> (if recursive == FileIngestionMethod_FileRecursive then ":r:" else ":")
-      <> Data.Text.Encoding.encodeUtf8 (System.Nix.Hash.encodeDigestWith Base16 h)
-      <> ":"
-
-computeStorePathForText
-  :: StoreDir
-  -> StorePathName
-  -> ByteString
-  -> (HashSet StorePath -> StorePath)
-computeStorePathForText storeDir nm =
-  makeTextPath storeDir nm
-  . Crypto.Hash.hash
+import Crypto.Hash qualified
+import System.Nix.Nar qualified
 
-computeStorePathForPath
-  :: StoreDir
-  -> StorePathName        -- ^ Name part of the newly created `StorePath`
-  -> FilePath             -- ^ Local `FilePath` to add
-  -> FileIngestionMethod  -- ^ Add target directory recursively
+digestPath
+  :: FilePath             -- ^ Local `FilePath` to add
+  -> ContentAddressMethod -- ^ target directory method
   -> PathFilter           -- ^ Path filter function
   -> RepairMode           -- ^ Only used by local store backend
-  -> IO StorePath
-computeStorePathForPath storeDir name pth recursive _pathFilter _repair = do
-  selectedHash <-
-    if recursive == FileIngestionMethod_FileRecursive
-      then recursiveContentHash
-      else flatContentHash
-  pure $ makeFixedOutputPath storeDir recursive selectedHash name
+  -> IO (Digest SHA256)
+digestPath pth method _pathFilter _repair =
+  case method of
+    ContentAddressMethod_Flat -> flatContentHash
+    ContentAddressMethod_NixArchive -> nixArchiveContentHash
+    ContentAddressMethod_Text -> flatContentHash
  where
-  recursiveContentHash :: IO (Digest SHA256)
-  recursiveContentHash =
+  nixArchiveContentHash :: IO (Digest SHA256)
+  nixArchiveContentHash =
     Crypto.Hash.hashFinalize
     <$> execStateT streamNarUpdate (Crypto.Hash.hashInit @SHA256)
 
@@ -128,3 +48,15 @@
     <$> System.Nix.Nar.narReadFile
           System.Nix.Nar.narEffectsIO
           pth
+
+computeStorePathForPath
+  :: StoreDir
+  -> StorePathName        -- ^ Name part of the newly created `StorePath`
+  -> FilePath             -- ^ Local `FilePath` to add
+  -> ContentAddressMethod -- ^ Add target directory methodly
+  -> PathFilter           -- ^ Path filter function
+  -> RepairMode           -- ^ Only used by local store backend
+  -> IO StorePath
+computeStorePathForPath storeDir name pth method pathFilter repair = do
+  selectedHash <- digestPath pth method pathFilter repair
+  pure $ makeFixedOutputPath storeDir method (HashAlgo_SHA256 :=> selectedHash) mempty name
diff --git a/tests/ReadOnlySpec.hs b/tests/ReadOnlySpec.hs
--- a/tests/ReadOnlySpec.hs
+++ b/tests/ReadOnlySpec.hs
@@ -2,124 +2,11 @@
 
 module ReadOnlySpec where
 
-import Data.Default.Class (Default(def))
-import Test.Hspec (Spec, describe, it, shouldBe, pendingWith)
-
-import Crypto.Hash (hash, Digest, SHA256(..))
-import Data.ByteString (ByteString)
-import System.Nix.StorePath (StorePath, StorePathName)
-import System.Nix.Store.Types (FileIngestionMethod(..))
-
-import qualified Data.HashSet
-import qualified System.Nix.StorePath
-
-import System.Nix.Store.ReadOnly
-
-testDigest :: Digest SHA256
-testDigest = Crypto.Hash.hash @ByteString "testDigest"
-
-testName :: StorePathName
-testName =
-    either undefined id
-  $ System.Nix.StorePath.mkStorePathName "testFixed"
-
-testPath :: StorePath
-testPath =
-    either undefined id
-  $ System.Nix.StorePath.parsePathFromText
-      def
-      "/nix/store/9472ijanf79nlkb5n1yh57s7867p1930-testFixed"
-
-testPath2 :: StorePath
-testPath2 =
-    either undefined id
-  $ System.Nix.StorePath.parsePathFromText
-      def
-      "/nix/store/iali40m5597kikibjxw8cx1ssxlqnii3-testFixed"
+import Test.Hspec (Spec, describe, it, pendingWith)
 
 spec :: Spec
 spec = do
   describe "ReadOnly" $ do
-    it "makeStorePath computes correct StorePath" $
-      (pure
-        $ makeStorePath
-            def
-            "test"
-            testDigest
-            testName
-      )
-      `shouldBe`
-      System.Nix.StorePath.parsePathFromText
-        def
-        "/nix/store/iali40m5597kikibjxw8cx1ssxlqnii3-testFixed"
-
-    describe "makeTextPath" $ do
-      it "computes correct StorePath for empty refs" $
-        (pure
-          $ makeTextPath
-              def
-              testName
-              testDigest
-              mempty
-        )
-        `shouldBe`
-        System.Nix.StorePath.parsePathFromText
-          def
-          "/nix/store/ync87sfmahhaqwnykzwbk31q96drm9vn-testFixed"
-
-      it "computes correct StorePath for nonempty refs" $
-        (pure
-          $ makeTextPath
-              def
-              testName
-              testDigest
-              (Data.HashSet.fromList [ testPath, testPath2 ])
-        )
-        `shouldBe`
-        System.Nix.StorePath.parsePathFromText
-          def
-          "/nix/store/jcvh84zapqndh8hva515d4y41s07n2g8-testFixed"
-
-    describe "makeFixedOuputPath" $ do
-      it "computes correct StorePath, recursive" $
-        (pure
-          $ makeFixedOutputPath
-              def
-              FileIngestionMethod_FileRecursive
-              testDigest
-              testName
-        )
-        `shouldBe`
-        System.Nix.StorePath.parsePathFromText
-          def
-          "/nix/store/c0cgdqy9i3smyh3as8c4s6fg6nvwdpzy-testFixed"
-
-      it "computes correct StorePath, non-recursive" $
-        (pure
-          $ makeFixedOutputPath
-              def
-              FileIngestionMethod_Flat
-              testDigest
-              testName
-        )
-        `shouldBe`
-        System.Nix.StorePath.parsePathFromText
-          def
-          "/nix/store/9472ijanf79nlkb5n1yh57s7867p1930-testFixed"
-
-    it "computeStorePathForText computes correct StorePath" $
-        (pure
-          $ computeStorePathForText
-              def
-              testName
-              "test"
-              (Data.HashSet.fromList [ testPath ])
-        )
-        `shouldBe`
-        System.Nix.StorePath.parsePathFromText
-          def
-          "/nix/store/838lq5qh5a88wsalcjpmj33bcnmpz3pc-testFixed"
-
-    describe "computeStorePathForForPath" $ do
+    describe "computeStorePathForPath" $ do
       it "computes correct StorePath" $
         pendingWith "needs IO and a sample directory to add"
