diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for prettyprinter-interp
+
+## 0.1.0.0 -- 2022-10-02
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2022, Peter Lebbing
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the
+   distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/prettyprinter-interp.cabal b/prettyprinter-interp.cabal
new file mode 100644
--- /dev/null
+++ b/prettyprinter-interp.cabal
@@ -0,0 +1,52 @@
+cabal-version:      2.4
+name:               prettyprinter-interp
+version:            0.1.0.0
+synopsis:           Efficient interpolation for Prettyprinter
+description:
+  This package provides efficient interpolation
+  of @[string-interpolate](https://hackage.haskell.org/package/string-interpolate)@
+  quasi quoters when used
+  with @[prettyprinter](https://hackage.haskell.org/package/prettyprinter)@.
+homepage:           https://github.com/DigitalBrains1/prettyprinter-interp
+bug-reports:        https://github.com/DigitalBrains1/prettyprinter-interp/issues
+license:            BSD-2-Clause
+license-file:       LICENSE
+author:             Peter Lebbing
+maintainer:         peter@digitalbrains.com
+copyright:          (C) 2022     , Peter Lebbing
+category:           Data, Text
+extra-source-files: CHANGELOG.md
+
+source-repository head
+  type:     git
+  location: https://github.com/DigitalBrains1/prettyprinter-interp
+source-repository this
+  type:     git
+  location: https://github.com/DigitalBrains1/prettyprinter-interp
+  tag:      v0.1.0.0
+
+library
+  exposed-modules:    Prettyprinter.Interpolate
+
+  build-depends:      base                      >=4.12      && < 4.18,
+                      prettyprinter             >=1.2       && < 1.8,
+                      string-interpolate        ^>=0.3.1,
+                      template-haskell,
+                      text                      >=1.2       && < 2.1,
+  hs-source-dirs:     src
+  default-language:   Haskell2010
+  ghc-options:        -Wall -Wcompat
+
+test-suite unittests
+  default-language:   Haskell2010
+  type:               exitcode-stdio-1.0
+  hs-source-dirs:     test
+  main-is:            unittests.hs
+  build-depends:      base,
+                      prettyprinter,
+                      prettyprinter-interp,
+                      string-interpolate,
+                      tasty                     >= 1.2      && < 1.5,
+                      tasty-hunit               ^>=0.10.0.2,
+                      text,
+  ghc-options:        -Wall -Wcompat
diff --git a/src/Prettyprinter/Interpolate.hs b/src/Prettyprinter/Interpolate.hs
new file mode 100644
--- /dev/null
+++ b/src/Prettyprinter/Interpolate.hs
@@ -0,0 +1,141 @@
+{-|
+  Copyright   :  (C) 2022     , Peter Lebbing
+  License     :  BSD2 (see the file LICENSE)
+  Maintainer  :  Peter Lebbing <peter@digitalbrains.com>
+
+  =Efficient interpolation for "Prettyprinter"
+
+  This module provides efficient interpolation of
+  [@string-interpolate@](https://hackage.haskell.org/package/string-interpolate)
+  quasi quoters when used with
+  [@prettyprinter@s](https://hackage.haskell.org/package/prettyprinter)
+  'Prettyprinter.Doc'uments.
+
+  The normal quasi quoters from @string-interpolate@ do work when used as a
+  @Doc@. Newlines are even converted to @Prettyprinter.@'Prettyprinter.line'.
+  However, this method is inefficient. The following code functions correctly:
+
+  @
+  {\-\# LANGUAGE OverloadedStrings \#-\}
+  {\-\# LANGUAGE QuasiQuotes \#-\}
+
+  module Main where
+
+  import Data.String.Interpolate
+  import Data.Text (Text)
+  import Prettyprinter
+
+  f :: 'Text'
+  f = "world"
+
+  g :: Doc ()
+  g = ['i'|Hello #{f}!|]
+
+  main :: IO ()
+  main = print g
+  @
+
+  However, what happens under the hood is that @f@ is converted to 'String', the
+  interpolated string is built manipulating @String@s, and then the output is
+  converted to 'Data.Text.Text' in
+  [@prettyprinter@](https://hackage.haskell.org/package/prettyprinter). The
+  following code is much better:
+
+  @
+  g = 'pretty' ([i|Hello #{f}!|] :: Text)
+  @
+
+  Now, the interpolated string is constructed as @Text@, and this is passed
+  cleanly into @Doc@ which also uses @Text@ as its underlying type for
+  representation of text. At no point is @f@ converted to @String@, and the
+  string construction benefits from the performance of @Text@. And again,
+  newlines are converted to 'Prettyprinter.line'.
+
+  This module defines wrapper quasi quoters that automatically perform the
+  @pretty@ invocation, and can simply be used as:
+
+  @
+  g = ['di'|Hello #{f}!|]
+  @
+-}
+
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+module Prettyprinter.Interpolate
+  ( di
+  , __di
+  , diii
+  , d__i'E
+  , d__i'L
+  , diii'E
+  , diii'L
+  ) where
+
+#if MIN_VERSION_prettyprinter(1,7,0)
+import Prettyprinter (Pretty(pretty))
+#else
+import Data.Text.Prettyprint.Doc (Pretty(pretty))
+#endif
+
+import Data.String.Interpolate
+import Data.Text (Text)
+import Language.Haskell.TH (Q)
+import Language.Haskell.TH.Quote (QuasiQuoter(..))
+import Language.Haskell.TH.Syntax (Name)
+
+wrapper :: Name -> QuasiQuoter -> QuasiQuoter
+wrapper nm wrapped = QuasiQuoter
+  { quoteExp = \s -> [| pretty ($(quoteExp wrapped s) :: Text) |]
+  , quotePat = const $ errQQType nm "pattern"
+  , quoteType = const $ errQQType nm "type"
+  , quoteDec = const $ errQQType nm "declaration"
+  }
+
+-- | Wrapper around the 'i' quasi quoter, producing a t'Prettyprinter.Doc'
+--
+-- Newlines in the text are converted to 'Prettyprinter.line'.
+di :: QuasiQuoter
+di = wrapper 'di i
+
+-- | Wrapper around the '__i' quasi quoter, producing a t'Prettyprinter.Doc'
+--
+-- Newlines in the text are converted to 'Prettyprinter.line'.
+__di :: QuasiQuoter
+__di = wrapper '__di __i
+
+-- | Wrapper around the 'iii' quasi quoter, producing a t'Prettyprinter.Doc'
+--
+-- Newlines in the text are converted to 'Prettyprinter.line'.
+diii :: QuasiQuoter
+diii = wrapper 'diii iii
+
+-- | Wrapper around the '__i'E' quasi quoter, producing a t'Prettyprinter.Doc'
+--
+-- Newlines in the text are converted to 'Prettyprinter.line'.
+d__i'E :: QuasiQuoter
+d__i'E = wrapper 'd__i'E __i'E
+
+-- | Wrapper around the '__i'L' quasi quoter, producing a t'Prettyprinter.Doc'
+--
+-- Newlines in the text are converted to 'Prettyprinter.line'.
+d__i'L :: QuasiQuoter
+d__i'L = wrapper 'd__i'L __i'L
+
+-- | Wrapper around the 'iii'E' quasi quoter, producing a t'Prettyprinter.Doc'
+--
+-- Newlines in the text are converted to 'Prettyprinter.line'.
+diii'E :: QuasiQuoter
+diii'E = wrapper 'diii'E iii'E
+
+-- | Wrapper around the 'iii'L' quasi quoter, producing a t'Prettyprinter.Doc'
+--
+-- Newlines in the text are converted to 'Prettyprinter.line'.
+diii'L :: QuasiQuoter
+diii'L = wrapper 'diii'L iii'L
+
+errQQ :: Name -> String -> Q a
+errQQ nm msg = fail $ show nm <> ": " <> msg
+
+errQQType :: Name -> String -> Q a
+errQQType nm ty = errQQ nm $ "This QuasiQuoter cannot be used as a " <> ty
diff --git a/test/unittests.hs b/test/unittests.hs
new file mode 100644
--- /dev/null
+++ b/test/unittests.hs
@@ -0,0 +1,29 @@
+{-|
+  Copyright   :  (C) 2022     , Peter Lebbing
+  License     :  BSD2 (see the file LICENSE)
+  Maintainer  :  Peter Lebbing <peter@digitalbrains.com>
+-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes #-}
+
+module Main where
+
+import Data.Text (Text)
+import Test.Tasty
+import Test.Tasty.HUnit
+
+import Prettyprinter.Interpolate
+
+f :: Text
+f = "world"
+
+basicFunc :: Assertion
+basicFunc = show [di|Hello #{f}!|] @?= "Hello world!"
+
+tests :: TestTree
+tests =
+  testCase "Basic functionality" basicFunc
+
+main :: IO ()
+main = defaultMain tests
