diff --git a/bench/JsonBench.hs b/bench/JsonBench.hs
--- a/bench/JsonBench.hs
+++ b/bench/JsonBench.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE OverloadedStrings, RecordWildCards #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE MagicHash, DeriveGeneric #-}
 
 module Main (main) where
 
@@ -10,6 +10,7 @@
 import Data.Aeson ((.:))
 import Data.Monoid ((<>))
 import Data.Text (Text)
+import GHC.Generics (Generic)
 import qualified Data.Aeson as Aeson
 import qualified Data.BufferBuilder.Json as Json
 import qualified Data.ByteString as BS
@@ -19,11 +20,11 @@
 import qualified Data.Vector.Unboxed as UnboxedVector
 
 data EyeColor = Green | Blue | Brown
-    deriving (Eq, Show)
+    deriving (Eq, Show, Generic)
 data Gender = Male | Female
-    deriving (Eq, Show)
+    deriving (Eq, Show, Generic)
 data Fruit = Apple | Strawberry | Banana
-    deriving (Eq, Show)
+    deriving (Eq, Show, Generic)
 data Friend = Friend
     { fId :: !Int
     , fName :: !Text
diff --git a/buffer-builder.cabal b/buffer-builder.cabal
--- a/buffer-builder.cabal
+++ b/buffer-builder.cabal
@@ -1,5 +1,5 @@
 name:                buffer-builder
-version:             0.2.4.0
+version:             0.2.4.1
 synopsis:            Library for efficiently building up buffers, one piece at a time
 description:
 
@@ -81,13 +81,8 @@
   build-depends: base ==4.*
                , buffer-builder
                , text
-               , tasty
-               , tasty-hunit
-               , tasty-th
-               , tasty-quickcheck
                , quickcheck-instances
-               , HUnit
-               , text
+               , HTF
                , vector
                , bytestring
                , attoparsec
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,7 @@
+0.2.4.1
+
+* Fix a bug with appendEscapedJsonText and Text buffers with nonzero offsets. (Thanks Joe Lee!)
+
 0.2.4.0
 
 * Add the ability to calculate the output length of a BufferBuilder without allocating or writing bytes
diff --git a/src/Data/BufferBuilder.hs b/src/Data/BufferBuilder.hs
--- a/src/Data/BufferBuilder.hs
+++ b/src/Data/BufferBuilder.hs
@@ -352,7 +352,7 @@
 appendEscapedJsonText !(Text arr ofs len) =
     let byteArray = aBA arr
     in withHandle $ \h ->
-        bw_append_json_escaped_utf16 h len (Ptr (byteArrayContents# byteArray) `plusPtr` ofs)
+        bw_append_json_escaped_utf16 h len (Ptr (byteArrayContents# byteArray) `plusPtr` (2 * ofs))
 {-# INLINE appendEscapedJsonText #-}
 
 -- | Append a percent-encoded ByteString.  All characters except for
diff --git a/test/BufferTest.hs b/test/BufferTest.hs
--- a/test/BufferTest.hs
+++ b/test/BufferTest.hs
@@ -1,73 +1,96 @@
+{-# OPTIONS_GHC -F -pgmF htfpp #-}
 {-# LANGUAGE MagicHash, OverloadedStrings, TemplateHaskell, FlexibleInstances #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
-module BufferTest (tests, main) where
+module BufferTest (htf_thisModulesTests) where
 
+import Test.Framework
+
 import qualified Data.ByteString.Char8 as BSC
-import Test.Tasty
-import Test.Tasty.TH
-import Test.Tasty.QuickCheck
-import Test.Tasty.HUnit
 import Data.BufferBuilder
 import Test.QuickCheck.Instances ()
 
-case_append_bytes :: Assertion
-case_append_bytes = do
+import qualified Data.Text as T
+import qualified Data.Text.Internal as TI
+
+getTextOffset :: T.Text -> Int
+getTextOffset (TI.Text _array offset _length) = offset
+
+test_append_bytes :: IO ()
+test_append_bytes = do
     let result = runBufferBuilder $ do
             appendChar8 'f'
             appendChar8 'o'
             appendChar8 'o'
-    assertEqual "matches" "foo" result
+    assertEqual "foo" result
 
-case_append_string :: Assertion
-case_append_string = do
+test_append_string :: IO ()
+test_append_string = do
     let result = runBufferBuilder $ do
             appendChar8 'f'
             appendChar8 'o'
             appendChar8 'o'
             appendBS "bar"
-    assertEqual "matches" "foobar" result
+    assertEqual "foobar" result
 
-case_append_literals :: Assertion
-case_append_literals = do
+test_append_json_escaped_text_with_zero_offset :: IO ()
+test_append_json_escaped_text_with_zero_offset = do
+    let t = "foo"
+    assertEqual 0 (getTextOffset t)
     let result = runBufferBuilder $ do
+            appendEscapedJsonText t
+            appendBS "bar"
+    assertEqual "\"foo\"bar" result
+
+test_append_json_escaped_text_with_nonzero_offset :: IO ()
+test_append_json_escaped_text_with_nonzero_offset = do
+    let [_, t] = T.split (== '-') "some_prefix-foo"
+    assertNotEqual 0 (getTextOffset t)
+    let result = runBufferBuilder $ do
+            appendEscapedJsonText t
+            appendBS "bar"
+    assertEqual "\"foo\"bar" result
+
+test_append_literals :: IO ()
+test_append_literals = do
+    let result = runBufferBuilder $ do
             appendLiteral "foo"#
             appendLiteral "bar"#
-    assertEqual "matches" "foobar" result
+    assertEqual "foobar" result
 
-case_append_url_encoded_safe :: Assertion
-case_append_url_encoded_safe = do
+test_append_url_encoded_safe :: IO ()
+test_append_url_encoded_safe = do
     let safe = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
     let result = runBufferBuilder $ do
             appendUrlEncoded safe
-    assertEqual "matches" safe result
+    assertEqual safe result
 
-case_append_url_encoded_unsafe :: Assertion
-case_append_url_encoded_unsafe = do
+test_append_url_encoded_unsafe :: IO ()
+test_append_url_encoded_unsafe = do
     let safe = "\0\1 /\\$%"
     let result = runBufferBuilder $ do
             appendUrlEncoded safe
-    assertEqual "matches" "%00%01%20%2f%5c%24%25" result
+    assertEqual "%00%01%20%2f%5c%24%25" result
 
-case_query_current_length :: Assertion
-case_query_current_length = do
+test_query_current_length :: IO ()
+test_query_current_length = do
     let ((f, s), result) = runBufferBuilder' $ do
             appendBS "foo"
             first <- currentLength
             appendBS "bar"
             second <- currentLength
             return (first, second)
-    assertEqual "first length" 3 f
-    assertEqual "second length" 6 s
-    assertEqual "result" "foobar" result
+    assertEqual 3 f
+    assertEqual 6 s
+    assertEqual "foobar" result
 
-case_calculate_length :: Assertion
-case_calculate_length = do
+test_calculate_length :: IO ()
+test_calculate_length = do
     let first = appendBS "foo"
     let second = first >> appendBS "bar"
 
-    assertEqual "first length" 3 $ calculateLength first
-    assertEqual "second length" 6 $ calculateLength second
+    assertEqual 3 $ calculateLength first
+    assertEqual 6 $ calculateLength second
 
 prop_match_intDec :: Int -> Bool
 prop_match_intDec i = runBufferBuilder (appendDecimalSignedInt i) == (BSC.pack $ show i)
@@ -98,9 +121,3 @@
 prop_length_calculation_matches_actual_length bb =
     let cc = bb >> return () in
     BSC.length (runBufferBuilder cc) == calculateLength cc
-
-tests :: TestTree
-tests = $(testGroupGenerator)
-
-main :: IO ()
-main = defaultMain tests
diff --git a/test/JsonTest.hs b/test/JsonTest.hs
--- a/test/JsonTest.hs
+++ b/test/JsonTest.hs
@@ -1,13 +1,12 @@
+{-# OPTIONS_GHC -F -pgmF htfpp #-}
 {-# LANGUAGE MagicHash, OverloadedStrings, TemplateHaskell, ExistentialQuantification #-}
 
-module JsonTest where
+module JsonTest (htf_thisModulesTests) where
 
+import Test.Framework
+
 import Data.Foldable (foldMap)
-import Test.Tasty
-import Test.Tasty.TH
 import qualified Data.Attoparsec.ByteString as Atto
-import Test.Tasty.HUnit
-import Test.Tasty.QuickCheck
 import Data.Monoid ((<>), Monoid (mconcat, mempty))
 import Data.String (IsString (..))
 import Data.BufferBuilder.Json
@@ -19,28 +18,28 @@
 import qualified Data.Text as Text
 import qualified Data.Vector as Vector
 
-ae :: (IsString a, Show a, Eq a) => String -> a -> Assertion
-ae expected actual = assertEqual expected (fromString expected) actual
+ae :: (IsString a, Show a, Eq a) => String -> a -> IO ()
+ae expected actual = assertEqual (fromString expected) actual
 
-case_encode_int :: IO ()
-case_encode_int = do
+test_encode_int :: IO ()
+test_encode_int = do
     ae "-42" (encodeJson (-42::Int))
     ae "9" (encodeJson (9::Int))
 
-case_encode_bool :: IO ()
-case_encode_bool = do
+test_encode_bool :: IO ()
+test_encode_bool = do
     ae "true" (encodeJson True)
     ae "false" (encodeJson False)
 
-case_encode_text :: IO ()
-case_encode_text = do
+test_encode_text :: IO ()
+test_encode_text = do
     ae "\"hello\"" (encodeJson ("hello" :: Text))
     ae "\"\"" (encodeJson ("" :: Text))
 
     ae "\"\\\"\\\\\\n\\r\\t\"" (encodeJson (fromString ['\"', '\\', '\n', '\r', '\t'] :: Text))
 
-case_encode_object :: IO ()
-case_encode_object = do
+test_encode_object :: IO ()
+test_encode_object = do
     ae "{\"key\":\"value\"}" (encodeJson ("key" .= ("value" :: Text)))
     ae "{\"key\":\"value\",\"key2\":[5,6,7]}"
         (encodeJson ("key" .= ("value" :: Text) <> "key2" .= ([5,6,7] :: [Int])))
@@ -64,21 +63,21 @@
 instance ToJsonString CustomThing where
     toJsonString = unsafeStringUtf8Builder . encodeCustomThing
 
-case_encode_object_with_custom_typeclasses :: IO ()
-case_encode_object_with_custom_typeclasses = do
+test_encode_object_with_custom_typeclasses :: IO ()
+test_encode_object_with_custom_typeclasses = do
     ae "{\"key\":\"value\"}" $ encodeJson $ ("key" :: Text) `row` ("value" :: Text)
     ae "{\"foo/bar/baz\":\"foo/bar/baz\"}" $ encodeJson $ CustomThing `row` CustomThing
 
-case_monoid_laws :: IO ()
-case_monoid_laws = do
+test_monoid_laws :: IO ()
+test_monoid_laws = do
     -- TODO QuickCheck
     let a = "key" .= ("value" :: Text)
         b = "key2" .= (999 :: Int)
         c = "key3" .= ([1,2,3] :: [Int])
-    assertEqual "Left identity" (encodeJson a) (encodeJson (mempty <> a))
-    assertEqual "Right identity" (encodeJson a) (encodeJson (a <> mempty))
-    assertEqual "Associativity" (encodeJson (a <> (b <> c))) (encodeJson ((a <> b) <> c))
-    assertEqual "mconcat" (encodeJson (mconcat [a, b, c])) (encodeJson (a <> b <> c))
+    assertEqual {-Left identity-} (encodeJson a) (encodeJson (mempty <> a))
+    assertEqual {-Right identity-} (encodeJson a) (encodeJson (a <> mempty))
+    assertEqual {-Associativity-} (encodeJson (a <> (b <> c))) (encodeJson ((a <> b) <> c))
+    assertEqual {-mconcat-} (encodeJson (mconcat [a, b, c])) (encodeJson (a <> b <> c))
 
 data JsonValue = forall a. ToJson a => JsonValue a
 
@@ -137,9 +136,3 @@
     case decodeJsonFragment $ encodeJson jv :: Maybe Aeson.Value of
         Just _ -> True
         Nothing -> False
-
-tests :: TestTree
-tests = $(testGroupGenerator)
-
-main :: IO ()
-main = defaultMain tests
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,17 +1,12 @@
-{-# LANGUAGE TemplateHaskell, OverloadedStrings, MagicHash #-}
+{-# OPTIONS_GHC -F -pgmF htfpp #-}
 
-import Test.Tasty
+module Main where
 
-import qualified BufferTest
-import qualified Utf8Test
-import qualified JsonTest
+import Test.Framework
 
-allTests :: TestTree
-allTests = testGroup "all tests"
-    [ BufferTest.tests
-    , Utf8Test.tests
-    , JsonTest.tests
-    ]
+import {-@ HTF_TESTS @-} BufferTest
+import {-@ HTF_TESTS @-} Utf8Test
+import {-@ HTF_TESTS @-} JsonTest
 
 main :: IO ()
-main = defaultMain allTests
+main = htfMain htf_importedTests
diff --git a/test/Utf8Test.hs b/test/Utf8Test.hs
--- a/test/Utf8Test.hs
+++ b/test/Utf8Test.hs
@@ -1,30 +1,24 @@
+{-# OPTIONS_GHC -F -pgmF htfpp #-}
 {-# LANGUAGE MagicHash, OverloadedStrings, TemplateHaskell #-}
 
-module Utf8Test (tests, main) where
+module Utf8Test (htf_thisModulesTests) where
 
-import Test.Tasty
-import Test.Tasty.TH
-import Test.Tasty.HUnit
+import Test.Framework
+
 import Data.BufferBuilder.Utf8
 import qualified Data.Text as Text
 import qualified Data.Text.Encoding as TE
 
-case_append_string :: Assertion
-case_append_string = do
+test_append_string :: IO ()
+test_append_string = do
     let str = "foo\NUL\1234"
     let bb = runUtf8Builder $ do
             appendString str
-    assertEqual "matches" (Text.pack str) $ TE.decodeUtf8 bb
+    assertEqual (Text.pack str) $ TE.decodeUtf8 bb
 
-case_append_chars :: Assertion
-case_append_chars = do
+test_append_chars :: IO ()
+test_append_chars = do
     let bb = runUtf8Builder $ do
             appendChar '\NUL'
             appendChar '\x1234'
-    assertEqual "matches" (TE.encodeUtf8 "\NUL\x1234") bb
-
-tests :: TestTree
-tests = $(testGroupGenerator)
-
-main :: IO ()
-main = defaultMain tests
+    assertEqual (TE.encodeUtf8 "\NUL\x1234") bb
