diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,9 @@
+# Changelog for safe-coloured-text
+
+## [0.2.0.0] - 2022-06-19
+
+### Changed
+
+* The default output of the library is now `Text`, so that the encoding is not chosen for the user.
+  Existing functions for rendering to `ByteString`s have been deprecated but not removed.
+* Internal character constants have been changed from `Word8` to `Char`.
diff --git a/safe-coloured-text.cabal b/safe-coloured-text.cabal
--- a/safe-coloured-text.cabal
+++ b/safe-coloured-text.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.34.4.
+-- This file has been generated from package.yaml by hpack version 0.34.7.
 --
 -- see: https://github.com/sol/hpack
 
 name:           safe-coloured-text
-version:        0.1.0.0
+version:        0.2.0.0
 synopsis:       Safely output coloured text
 category:       User Interfaces
 homepage:       https://github.com/NorfairKing/safe-coloured-text#readme
@@ -16,6 +16,8 @@
 license:        MIT
 license-file:   LICENSE
 build-type:     Simple
+extra-source-files:
+    CHANGELOG.md
 
 source-repository head
   type: git
diff --git a/src/Text/Colour.hs b/src/Text/Colour.hs
--- a/src/Text/Colour.hs
+++ b/src/Text/Colour.hs
@@ -62,32 +62,75 @@
 
     -- * Rendering
 
-    -- ** Rendering chunks to bytestring builders
-    renderChunks,
-    renderChunk,
+    -- ** Rendering chunks to strict bytestring in UTF8
+    renderChunksUtf8BS,
+    renderChunkUtf8BS,
 
-    -- ** Rendering chunks to strict bytestring
+    -- ** Rendering chunks to lazy bytestring builders in UTF8
+    renderChunksUtf8BSBuilder,
+    renderChunkUtf8BSBuilder,
+
+    -- ** Rendering chunks to strict Text
+    renderChunksText,
+    renderChunkText,
+
+    -- ** Rendering chunks to lazy text
+    renderChunksLazyText,
+    renderChunkLazyText,
+
+    -- ** Rendering chunks to lazy text builder
+    renderChunksBuilder,
+    renderChunkBuilder,
+
+    -- ** Decrecated rendering chunks to strict bytestring in UTF8
     renderChunksBS,
     renderChunkBS,
 
+    -- ** Deprecated rendering chunks to lazy bytestring builders in UTF8
+    renderChunks,
+    renderChunk,
+
     -- * IO
     TerminalCapabilities (..),
 
     -- ** Outputting chunks directly
+    putChunksUtf8With,
+    putChunksLocaleWith,
+    hPutChunksUtf8With,
+    hPutChunksLocaleWith,
     putChunksWith,
     hPutChunksWith,
   )
 where
 
 import qualified Data.ByteString.Builder as SBB
+import qualified Data.Text.IO as TIO
 import System.IO
 import Text.Colour.Capabilities
 import Text.Colour.Chunk
 
 -- | Print a list of chunks to stdout with given 'TerminalCapabilities'.
+putChunksUtf8With :: TerminalCapabilities -> [Chunk] -> IO ()
+putChunksUtf8With tc = hPutChunksUtf8With tc stdout
+
+-- | Print a list of chunks to stdout with given 'TerminalCapabilities' in an encoding according to the system's locale.
+putChunksLocaleWith :: TerminalCapabilities -> [Chunk] -> IO ()
+putChunksLocaleWith tc = hPutChunksWith tc stdout
+
+-- | Deprecated synonym of 'putChunksUtf8With'
 putChunksWith :: TerminalCapabilities -> [Chunk] -> IO ()
-putChunksWith tc = hPutChunksWith tc stdout
+putChunksWith = putChunksUtf8With
+{-# DEPRECATED putChunksWith "Use putChunksLocaleWith, or putChunksUtf8With if you must." #-}
 
 -- | Print a list of chunks to the given 'Handle' with given 'TerminalCapabilities'.
+hPutChunksUtf8With :: TerminalCapabilities -> Handle -> [Chunk] -> IO ()
+hPutChunksUtf8With tc h cs = SBB.hPutBuilder h $ renderChunksUtf8BSBuilder tc cs
+
+-- | Print a list of chunks to the given 'Handle' with given 'TerminalCapabilities' in an encoding according to the system's locale.
+hPutChunksLocaleWith :: TerminalCapabilities -> Handle -> [Chunk] -> IO ()
+hPutChunksLocaleWith tc h cs = TIO.hPutStr h $ renderChunksText tc cs
+
+-- | Deprecated synonym of 'hPutChunksUtf8With'
 hPutChunksWith :: TerminalCapabilities -> Handle -> [Chunk] -> IO ()
-hPutChunksWith tc h cs = SBB.hPutBuilder h $ renderChunks tc cs
+hPutChunksWith = hPutChunksUtf8With
+{-# DEPRECATED hPutChunksWith "Use hPutChunksLocaleWith, or hPutChunksUtf8With if you must." #-}
diff --git a/src/Text/Colour/Chunk.hs b/src/Text/Colour/Chunk.hs
--- a/src/Text/Colour/Chunk.hs
+++ b/src/Text/Colour/Chunk.hs
@@ -5,13 +5,15 @@
 module Text.Colour.Chunk where
 
 import Data.ByteString (ByteString)
-import Data.ByteString.Builder (Builder)
-import qualified Data.ByteString.Builder as SBB
-import qualified Data.ByteString.Lazy as LB
+import qualified Data.ByteString.Builder as ByteString
 import Data.Maybe
 import Data.String
 import Data.Text (Text)
 import qualified Data.Text.Encoding as TE
+import qualified Data.Text.Lazy as LT
+import qualified Data.Text.Lazy.Builder as LTB
+import qualified Data.Text.Lazy.Builder as Text
+import qualified Data.Text.Lazy.Encoding as LTE
 import Data.Validity
 import Data.Word
 import GHC.Generics (Generic)
@@ -49,27 +51,71 @@
   Colour8Bit {} -> tc < With8BitColours
   Colour24Bit {} -> tc < With24BitColours
 
--- | Render a chunk directly to bytestring.
+-- | Render chunks directly to a UTF8-encoded 'Bytestring'.
+renderChunksUtf8BS :: Foldable f => TerminalCapabilities -> f Chunk -> ByteString
+renderChunksUtf8BS tc = TE.encodeUtf8 . renderChunksText tc
+
+-- | Deprecated synonym for 'renderChunksUtf8BS'
 renderChunksBS :: Foldable f => TerminalCapabilities -> f Chunk -> ByteString
-renderChunksBS tc = LB.toStrict . SBB.toLazyByteString . renderChunks tc
+renderChunksBS = renderChunksUtf8BS
+{-# DEPRECATED renderChunksBS "Use renderChunksText, or renderChunksUtf8BS if you must." #-}
 
--- | Render chunks to a bytestring builder
-renderChunks :: Foldable f => TerminalCapabilities -> f Chunk -> Builder
-renderChunks tc = foldMap (renderChunk tc)
+-- | Render chunks to a UTF8-encoded 'ByteString' 'Bytestring.Builder'.
+renderChunksUtf8BSBuilder :: Foldable f => TerminalCapabilities -> f Chunk -> ByteString.Builder
+renderChunksUtf8BSBuilder tc = foldMap (renderChunkUtf8BSBuilder tc)
 
--- | Render a chunk directly to bytestring.
+-- | Deprecated synonym for 'renderChunksUtf8BSBuilder'
+renderChunks :: Foldable f => TerminalCapabilities -> f Chunk -> ByteString.Builder
+renderChunks = renderChunksUtf8BSBuilder
+{-# DEPRECATED renderChunks "Use renderChunksBuilder, or renderChunksUtf8BSBuilder if you must." #-}
+
+-- | Render chunks directly to strict 'Text'.
+renderChunksText :: Foldable f => TerminalCapabilities -> f Chunk -> Text
+renderChunksText tc = LT.toStrict . renderChunksLazyText tc
+
+-- | Render chunks directly to lazy 'LT.Text'.
+renderChunksLazyText :: Foldable f => TerminalCapabilities -> f Chunk -> LT.Text
+renderChunksLazyText tc = LTB.toLazyText . renderChunksBuilder tc
+
+-- | Render chunks to a lazy 'LT.Text' 'Text.Builder'
+renderChunksBuilder :: Foldable f => TerminalCapabilities -> f Chunk -> Text.Builder
+renderChunksBuilder tc = foldMap (renderChunkBuilder tc)
+
+-- | Render a chunk directly to a UTF8-encoded 'Bytestring'.
+renderChunkUtf8BS :: TerminalCapabilities -> Chunk -> ByteString
+renderChunkUtf8BS tc = TE.encodeUtf8 . renderChunkText tc
+
+-- | Deprecated synonym for 'renderChunkUtf8BS'
 renderChunkBS :: TerminalCapabilities -> Chunk -> ByteString
-renderChunkBS tc = LB.toStrict . SBB.toLazyByteString . renderChunk tc
+renderChunkBS = renderChunkUtf8BS
+{-# DEPRECATED renderChunkBS "Use renderChunkText, or renderChunkUtf8BS if you must." #-}
 
--- | Render a chunk to a bytestring builder
-renderChunk :: TerminalCapabilities -> Chunk -> Builder
-renderChunk tc c@Chunk {..} =
+-- | Render a chunk directly to a UTF8-encoded 'Bytestring' 'ByteString.Builder'.
+renderChunkUtf8BSBuilder :: TerminalCapabilities -> Chunk -> ByteString.Builder
+renderChunkUtf8BSBuilder tc = LTE.encodeUtf8Builder . renderChunkLazyText tc
+
+-- | Deprecated synonym for 'renderChunkUtf8BSBuilder'
+renderChunk :: TerminalCapabilities -> Chunk -> ByteString.Builder
+renderChunk = renderChunkUtf8BSBuilder
+{-# DEPRECATED renderChunk "Use renderChunkBuilder, or renderChunkUtf8BSBuilder if you must." #-}
+
+-- | Render a chunk directly to strict 'Text'.
+renderChunkText :: TerminalCapabilities -> Chunk -> Text
+renderChunkText tc = LT.toStrict . renderChunkLazyText tc
+
+-- | Render a chunk directly to strict 'LT.Text'.
+renderChunkLazyText :: TerminalCapabilities -> Chunk -> LT.Text
+renderChunkLazyText tc = LTB.toLazyText . renderChunkBuilder tc
+
+-- | Render a chunk to a lazy 'LT.Text' 'Text.Builder'
+renderChunkBuilder :: TerminalCapabilities -> Chunk -> Text.Builder
+renderChunkBuilder tc c@Chunk {..} =
   if plainChunk tc c
-    then SBB.byteString (TE.encodeUtf8 chunkText)
+    then LTB.fromText chunkText
     else
       mconcat
-        [ renderCSI (SGR $ chunkSGR tc c),
-          SBB.byteString (TE.encodeUtf8 chunkText),
+        [ renderCSI (SGR (chunkSGR tc c)),
+          LTB.fromText chunkText,
           renderCSI (SGR [Reset])
         ]
 
diff --git a/src/Text/Colour/Code.hs b/src/Text/Colour/Code.hs
--- a/src/Text/Colour/Code.hs
+++ b/src/Text/Colour/Code.hs
@@ -4,11 +4,13 @@
 module Text.Colour.Code where
 
 import Data.ByteString (ByteString)
-import Data.ByteString.Builder (Builder)
-import qualified Data.ByteString.Builder as SBB
-import qualified Data.ByteString.Internal as SBI
-import qualified Data.ByteString.Lazy as LB
 import Data.List
+import Data.Text (Text)
+import qualified Data.Text.Encoding as TE
+import qualified Data.Text.Lazy as LT
+import qualified Data.Text.Lazy.Builder as LTB
+import qualified Data.Text.Lazy.Builder as Text
+import qualified Data.Text.Lazy.Builder.Int as LTB
 import Data.Validity
 import Data.Validity.ByteString ()
 import Data.Validity.Text ()
@@ -16,14 +18,14 @@
 import GHC.Generics (Generic)
 
 -- https://en.wikipedia.org/wiki/Escape_character#ASCII_escape_character
-asciiEscape :: Word8
-asciiEscape = SBI.c2w '\ESC'
+asciiEscape :: Char
+asciiEscape = '\ESC'
 
-csiStart :: Word8
-csiStart = SBI.c2w '['
+csiStart :: Char
+csiStart = '['
 
-csiDelimiter :: Word8
-csiDelimiter = SBI.c2w ';'
+csiDelimiter :: Char
+csiDelimiter = ';'
 
 newtype CSI
   = SGR [SGR]
@@ -31,24 +33,39 @@
 
 instance Validity CSI
 
--- | Render a CSI directly to bytestring.
+-- | Render a CSI directly to 'ByteString' using UTF8.
+--
 -- You probably want to use 'renderCSI' instead.
 -- This is just for testing.
-renderCSIBS :: CSI -> ByteString
-renderCSIBS = LB.toStrict . SBB.toLazyByteString . renderCSI
+renderCSIUtf8BS :: CSI -> ByteString
+renderCSIUtf8BS = TE.encodeUtf8 . renderCSIText
 
+-- | Render a CSI directly to strict 'Text'.
+--
+-- You probably want to use 'renderCSI' instead.
+-- This is just for testing.
+renderCSIText :: CSI -> Text
+renderCSIText = LT.toStrict . renderCSILazyText
+
+-- | Render a CSI directly to lazy 'LT.Text'.
+--
+-- You probably want to use 'renderCSI' instead.
+-- This is just for testing.
+renderCSILazyText :: CSI -> LT.Text
+renderCSILazyText = LTB.toLazyText . renderCSI
+
 -- https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_(Control_Sequence_Introducer)_sequences
-renderCSI :: CSI -> Builder
+renderCSI :: CSI -> Text.Builder
 renderCSI =
   let csi ps c =
         mconcat
-          [ SBB.word8 asciiEscape,
-            SBB.word8 csiStart,
-            csiParamsToWords ps,
-            SBB.word8 c
+          [ LTB.singleton asciiEscape,
+            LTB.singleton csiStart,
+            renderCSIParams ps,
+            LTB.singleton c
           ]
    in \case
-        SGR sgrs -> csi (concatMap sgrToCSIParams sgrs) (SBI.c2w 'm')
+        SGR sgrs -> csi (concatMap sgrToCSIParams sgrs) 'm'
 
 -- https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
 data SGR
@@ -67,13 +84,13 @@
 
 instance Validity SGR
 
-csiParamsToWords :: [Word8] -> Builder
-csiParamsToWords = mconcat . intersperse (SBB.word8 csiDelimiter) . map csiParamToWord
+renderCSIParams :: [Word8] -> Text.Builder
+renderCSIParams = mconcat . intersperse (LTB.singleton csiDelimiter) . map renderCSIParam
 
-csiParamToWord :: Word8 -> Builder
-csiParamToWord = \case
+renderCSIParam :: Word8 -> Text.Builder
+renderCSIParam = \case
   0 -> mempty
-  w -> SBB.word8Dec w
+  w -> LTB.decimal w
 
 sgrToCSIParams :: SGR -> [Word8]
 sgrToCSIParams = \case
