diff --git a/json-encoder.cabal b/json-encoder.cabal
--- a/json-encoder.cabal
+++ b/json-encoder.cabal
@@ -1,9 +1,9 @@
 name:
   json-encoder
 version:
-  0.1.3.1
+  0.1.5
 synopsis:
-  A very fast single-pass JSON encoder with a declarative DSL
+  A direct-to-bytes single-pass JSON encoder with a declarative DSL
 description:
 category:
   JSON, Codec
@@ -38,24 +38,23 @@
   hs-source-dirs:
     library
   default-extensions:
-    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, ImpredicativeTypes, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples
+    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples
   default-language:
     Haskell2010
   other-modules:
     JSONEncoder.Prelude
     JSONEncoder.Builders
-    JSONEncoder.ByteStrings
   exposed-modules:
     JSONEncoder
   build-depends:
     --
     text == 1.*,
     bytestring >= 0.10 && < 0.11,
-    bytestring-tree-builder >= 0.2.2.1 && < 0.3,
+    bytestring-tree-builder >= 0.2.4 && < 0.3,
     scientific >= 0.3 && < 0.4,
     --
     contravariant-extras == 0.3.*,
     contravariant >= 1.3 && < 2,
+    semigroups >= 0.18 && < 0.19,
     -- 
-    base-prelude >= 0.1.19 && < 0.2,
-    base >= 4.6 && < 5
+    base-prelude >= 0.1.21 && < 0.2
diff --git a/library/JSONEncoder.hs b/library/JSONEncoder.hs
--- a/library/JSONEncoder.hs
+++ b/library/JSONEncoder.hs
@@ -25,12 +25,12 @@
 where
 
 import JSONEncoder.Prelude hiding (length, null)
-import ByteString.TreeBuilder
+import qualified ByteString.TreeBuilder as Builders
 import qualified JSONEncoder.Builders as Builders
 import qualified Data.Scientific
 
 
-run :: Value a -> a -> Builder
+run :: Value a -> a -> Builders.Builder
 run (Value (Op producer)) input =
   producer input
 
@@ -39,7 +39,7 @@
 -------------------------
 
 newtype Value a =
-  Value (Op Builder a)
+  Value (Op Builders.Builder a)
   deriving (Contravariant, Divisible, Decidable)
 
 null :: Value ()
@@ -57,7 +57,7 @@
 number_integral :: Integral a => Value a
 number_integral =
   Value $ Op $
-  fromString . show . toInteger
+  Builders.asciiIntegral
 
 number_scientific :: Value Data.Scientific.Scientific
 number_scientific =
@@ -92,7 +92,7 @@
 -------------------------
 
 newtype Object a =
-  Object (Op Builder a)
+  Object (Op Builders.Builder a)
   deriving (Contravariant)
 
 instance Divisible Object where
@@ -115,6 +115,8 @@
   mappend (Object (Op producer1)) (Object (Op producer2)) =
     Object (Op (Builders.appendWithIncut (Builders.asciiChar ',') <$> producer1 <*> producer2))
 
+instance Semigroup (Object a)
+
 field :: Text -> Value a -> Object a
 field name (Value (Op producer)) =
   Object $ Op $ 
@@ -127,7 +129,7 @@
 -------------------------
 
 newtype Array a =
-  Array (Op Builder a)
+  Array (Op Builders.Builder a)
   deriving (Contravariant)
 
 -- |
@@ -154,7 +156,7 @@
 -------------------------
 
 newtype Hetero a =
-  Hetero (Op Builder a)
+  Hetero (Op Builders.Builder a)
   deriving (Contravariant)
 
 instance Divisible Hetero where
@@ -176,6 +178,8 @@
     Hetero (Op (const mempty))
   mappend (Hetero (Op producer1)) (Hetero (Op producer2)) =
     Hetero (Op (Builders.appendWithIncut (Builders.asciiChar ',') <$> producer1 <*> producer2))
+
+instance Semigroup (Hetero a)
 
 element :: Value a -> Hetero a
 element (Value op) =
diff --git a/library/JSONEncoder/Builders.hs b/library/JSONEncoder/Builders.hs
--- a/library/JSONEncoder/Builders.hs
+++ b/library/JSONEncoder/Builders.hs
@@ -2,7 +2,6 @@
 
 import JSONEncoder.Prelude hiding (length)
 import ByteString.TreeBuilder
-import qualified JSONEncoder.ByteStrings as ByteStrings
 import qualified Data.Text
 
 
@@ -19,16 +18,6 @@
     else if length b == 0
       then a
       else a <> incut <> b
-
-{-# INLINE asciiChar #-}
-asciiChar :: Char -> Builder
-asciiChar =
-  byte . fromIntegral . ord
-
-{-# INLINE utf8Char #-}
-utf8Char :: Char -> Builder
-utf8Char =
-  byteString . ByteStrings.utf8Char
 
 {-# INLINABLE stringEncodedChar #-}
 stringEncodedChar :: Char -> Builder
diff --git a/library/JSONEncoder/ByteStrings.hs b/library/JSONEncoder/ByteStrings.hs
deleted file mode 100644
--- a/library/JSONEncoder/ByteStrings.hs
+++ /dev/null
@@ -1,60 +0,0 @@
-module JSONEncoder.ByteStrings where
-
-import JSONEncoder.Prelude
-import Foreign
-import qualified Data.ByteString.Internal as C
-
-
-{-# INLINE utf8Char #-}
-utf8Char :: Char -> ByteString
-utf8Char =
-  utf8Ord . ord
-
-{-# INLINE utf8Ord #-}
-utf8Ord :: Int -> ByteString
-utf8Ord x =
-  if
-    | x <= 0x7F ->
-      bytes1 (fromIntegral x)
-    | x <= 0x07FF ->
-      bytes2 (fromIntegral ((x `shiftR` 6) + 0xC0))
-             (fromIntegral ((x .&. 0x3F) + 0x80))
-    | x <= 0xFFFF ->
-      bytes3 (fromIntegral (x `shiftR` 12) + 0xE0)
-             (fromIntegral ((x `shiftR` 6) .&. 0x3F) + 0x80)
-             (fromIntegral (x .&. 0x3F) + 0x80)
-    | otherwise ->
-      bytes4 (fromIntegral (x `shiftR` 18) + 0xF0)
-             (fromIntegral ((x `shiftR` 12) .&. 0x3F) + 0x80)
-             (fromIntegral ((x `shiftR` 6) .&. 0x3F) + 0x80)
-             (fromIntegral (x .&. 0x3F) + 0x80)
-
-{-# INLINE bytes1 #-}
-bytes1 :: Word8 -> ByteString
-bytes1 byte1 =
-  C.unsafeCreate 1 $ \ptr -> do
-    pokeByteOff ptr 0 byte1
-
-{-# INLINE bytes2 #-}
-bytes2 :: Word8 -> Word8 -> ByteString
-bytes2 byte1 byte2 =
-  C.unsafeCreate 2 $ \ptr -> do
-    pokeByteOff ptr 0 byte1
-    pokeByteOff ptr 1 byte2
-
-{-# INLINE bytes3 #-}
-bytes3 :: Word8 -> Word8 -> Word8 -> ByteString
-bytes3 byte1 byte2 byte3 =
-  C.unsafeCreate 3 $ \ptr -> do
-    pokeByteOff ptr 0 byte1
-    pokeByteOff ptr 1 byte2
-    pokeByteOff ptr 2 byte3
-
-{-# INLINE bytes4 #-}
-bytes4 :: Word8 -> Word8 -> Word8 -> Word8 -> ByteString
-bytes4 byte1 byte2 byte3 byte4 =
-  C.unsafeCreate 4 $ \ptr -> do
-    pokeByteOff ptr 0 byte1
-    pokeByteOff ptr 1 byte2
-    pokeByteOff ptr 2 byte3
-    pokeByteOff ptr 3 byte4
diff --git a/library/JSONEncoder/Prelude.hs b/library/JSONEncoder/Prelude.hs
--- a/library/JSONEncoder/Prelude.hs
+++ b/library/JSONEncoder/Prelude.hs
@@ -4,13 +4,9 @@
 )
 where
 
--- base
--------------------------
-import Numeric as Exports
-
 -- base-prelude
 -------------------------
-import BasePrelude as Exports hiding (fail, Alt)
+import BasePrelude as Exports hiding (fail, Alt, (<>), First(..), Last(..))
 
 -- contravariant
 -------------------------
@@ -20,6 +16,10 @@
 -- contravariant-extras
 -------------------------
 import Contravariant.Extras as Exports
+
+-- semigroups
+-------------------------
+import Data.Semigroup as Exports
 
 -- text
 -------------------------
