diff --git a/Text/Cassius.hs b/Text/Cassius.hs
--- a/Text/Cassius.hs
+++ b/Text/Cassius.hs
@@ -16,7 +16,6 @@
     ) where
 
 import Text.ParserCombinators.Parsec hiding (Line)
-import Data.Neither (AEither (..), either)
 import Data.Traversable (sequenceA)
 import Control.Applicative ((<$>))
 import Data.List (intercalate)
@@ -26,14 +25,14 @@
 import Text.Blaze.Builder.Core (Builder, fromByteString, toLazyByteString)
 import Text.Blaze.Builder.Utf8 (fromString)
 import Data.Maybe (catMaybes)
-import Prelude hiding (either)
 import qualified Data.ByteString.Char8 as S8
-import qualified Data.ByteString.UTF8 as BSU
 import qualified Data.ByteString.Lazy as L
 import Data.Monoid
 import Data.Word (Word8)
 import Data.Bits
 import System.IO.Unsafe (unsafePerformIO)
+import Text.Utf8
+import Control.Applicative (Applicative (..))
 
 data Color = Color Word8 Word8 Word8
     deriving Show
@@ -271,8 +270,7 @@
     QuasiQuoter { quoteExp = e }
   where
     e s = do
-        let a = either (error . show) id
-              $ parse parseLines s s
+        let a = either (error . show) id $ parse parseLines s s
         let b = flip map a $ \(_, l) ->
                     case l of
                         LinePair x y -> CPSimple x y
@@ -292,13 +290,13 @@
 cassiusFromString :: String -> Q Exp
 cassiusFromString s = do
     let a = either (error . show) id $ parse parseLines s s
-    let b = either (error . unlines) id
+    let b = aeither (error . unlines) id
           $ sequenceA $ map (nestToDec True) $ nestLines a
     contentsToCassius $ concatMap render $ concatMap flatDec b
 
 contentToCss :: Name -> Content -> Q Exp
 contentToCss _ (ContentRaw s') = do
-    let d = S8.unpack $ BSU.fromString s'
+    let d = charsToOctets s'
     ts <- [|Css . fromByteString . S8.pack|]
     return $ ts `AppE` LitE (StringL d)
 contentToCss _ (ContentVar d) = do
@@ -328,7 +326,7 @@
 
 cassiusFile :: FilePath -> Q Exp
 cassiusFile fp = do
-    contents <- fmap BSU.toString $ qRunIO $ S8.readFile fp
+    contents <- fmap bsToChars $ qRunIO $ S8.readFile fp
     cassiusFromString contents
 
 data VarType = VTPlain | VTUrl | VTUrlParam | VTMixin
@@ -363,7 +361,7 @@
 
 cassiusFileDebug :: FilePath -> Q Exp
 cassiusFileDebug fp = do
-    s <- fmap BSU.toString $ qRunIO $ S8.readFile fp
+    s <- fmap bsToChars $ qRunIO $ S8.readFile fp
     let a = either (error . show) id $ parse parseLines s s
         b = concatMap (getVars . snd) a
     c <- mapM vtToExp b
@@ -372,9 +370,9 @@
 
 cassiusRuntime :: FilePath -> [(Deref, CDData url)] -> Cassius url
 cassiusRuntime fp cd render' = unsafePerformIO $ do
-    s <- fmap BSU.toString $ qRunIO $ S8.readFile fp
+    s <- fmap bsToChars $ qRunIO $ S8.readFile fp
     let a = either (error . show) id $ parse parseLines s s
-    let b = either (error . unlines) id
+    let b = aeither (error . unlines) id
           $ sequenceA $ map (nestToDec True) $ nestLines a
     return $ mconcat $ map go $ concatMap render $ concatMap flatDec b
   where
@@ -397,3 +395,17 @@
         case lookup d cd of
             Just (CDMixin (CassiusMixin m)) -> m render'
             _ -> error $ show d ++ ": expected CDMixin"
+
+data AEither a b = ALeft a | ARight b
+instance Functor (AEither a) where
+    fmap _ (ALeft a) = ALeft a
+    fmap f (ARight b) = ARight $ f b
+instance Monoid a => Applicative (AEither a) where
+    pure = ARight
+    ALeft x <*> ALeft y = ALeft $ x `mappend` y
+    ALeft x <*> _ = ALeft x
+    _ <*> ALeft y = ALeft y
+    ARight x <*> ARight y = ARight $ x y
+aeither :: (a -> c) -> (b -> c) -> AEither a b -> c
+aeither f _ (ALeft a) = f a
+aeither _ f (ARight b) = f b
diff --git a/Text/Hamlet/Debug.hs b/Text/Hamlet/Debug.hs
--- a/Text/Hamlet/Debug.hs
+++ b/Text/Hamlet/Debug.hs
@@ -9,21 +9,21 @@
 import Language.Haskell.TH.Syntax
 import qualified Data.ByteString.Char8 as S8
 import System.IO.Unsafe (unsafePerformIO)
-import qualified Data.ByteString.UTF8 as BSU
 import Control.Arrow
 import Data.Either
 import Control.Monad (forM)
+import Text.Utf8
 
 unsafeRenderTemplate :: FilePath -> HamletMap url
                      -> (url -> [(String, String)] -> String) -> Html
 unsafeRenderTemplate fp hd render = unsafePerformIO $ do
-    contents <- fmap BSU.toString $ S8.readFile fp
+    contents <- fmap bsToChars $ S8.readFile fp
     temp <- parseHamletRT defaultHamletSettings contents
     renderHamletRT' True temp hd render
 
 hamletFileDebug :: FilePath -> Q Exp
 hamletFileDebug fp = do
-    contents <- fmap BSU.toString $ qRunIO $ S8.readFile fp
+    contents <- fmap bsToChars $ qRunIO $ S8.readFile fp
     HamletRT docs <- qRunIO $ parseHamletRT defaultHamletSettings contents
     urt <- [|unsafeRenderTemplate|]
     render <- newName "render"
diff --git a/Text/Hamlet/Quasi.hs b/Text/Hamlet/Quasi.hs
--- a/Text/Hamlet/Quasi.hs
+++ b/Text/Hamlet/Quasi.hs
@@ -27,14 +27,13 @@
 import Language.Haskell.TH.Syntax
 import Language.Haskell.TH.Quote
 import Data.Char (isUpper, isDigit)
-import qualified Data.ByteString.UTF8 as BSU
-import qualified Data.ByteString.Lazy.UTF8 as BSLU
 import qualified Data.ByteString.Char8 as S8
 import Data.Monoid (Monoid (..))
 import Text.Blaze.Builder.Core (Builder, fromByteString, toLazyByteString)
 import Text.Blaze.Builder.Html (fromHtmlEscapedString)
 import Data.Maybe (fromMaybe)
 import Data.String
+import Text.Utf8
 
 instance IsString Html where
     fromString = Html . fromHtmlEscapedString
@@ -51,12 +50,10 @@
 docsToExp :: Scope -> [Doc] -> Q Exp
 docsToExp scope docs = do
     exps <- mapM (docToExp scope) docs
-    let stmts = map (BindS $ TupP []) exps
-    rnull <- [|return ()|]
-    return $ case exps of
-        [] -> rnull
-        [x] -> x
-        _ -> DoE $ stmts ++ [NoBindS rnull]
+    case exps of
+        [] -> [|return ()|]
+        [x] -> return x
+        _ -> return $ DoE $ map NoBindS exps
 
 docToExp :: Scope -> Doc -> Q Exp
 docToExp scope (DocForall list ident@(Ident name) inside) = do
@@ -102,7 +99,7 @@
 contentToExp :: Scope -> Content -> Q Exp
 contentToExp _ (ContentRaw s) = do
     os <- [|htmlToHamletMonad . Html . fromByteString . S8.pack|]
-    let s' = LitE $ StringL $ S8.unpack $ BSU.fromString s
+    let s' = LitE $ StringL $ charsToOctets s
     return $ os `AppE` s'
 contentToExp scope (ContentVar d) = do
     str <- [|htmlToHamletMonad . toHtml|]
@@ -174,7 +171,7 @@
 
 hamletFileWithSettings :: HamletSettings -> FilePath -> Q Exp
 hamletFileWithSettings set fp = do
-    contents <- fmap BSU.toString $ qRunIO $ S8.readFile fp
+    contents <- fmap bsToChars $ qRunIO $ S8.readFile fp
     hamletFromString set contents
 
 -- | Calls 'hamletFileWithSettings' with 'defaultHamletSettings'.
@@ -226,7 +223,7 @@
 newtype Html = Html Builder
     deriving Monoid
 instance Show Html where
-    show (Html b) = show $ BSLU.toString $ toLazyByteString b
+    show (Html b) = show $ lbsToChars $ toLazyByteString b
 instance Eq Html where
     (Html a) == (Html b) = toLazyByteString a == toLazyByteString b
 
diff --git a/Text/Julius.hs b/Text/Julius.hs
--- a/Text/Julius.hs
+++ b/Text/Julius.hs
@@ -17,10 +17,10 @@
 import Text.Blaze.Builder.Core (Builder, fromByteString, toLazyByteString)
 import Text.Blaze.Builder.Utf8 (fromString)
 import qualified Data.ByteString.Char8 as S8
-import qualified Data.ByteString.UTF8 as BSU
 import qualified Data.ByteString.Lazy as L
 import Data.Monoid
 import System.IO.Unsafe (unsafePerformIO)
+import Text.Utf8
 
 renderJavascript :: Javascript -> L.ByteString
 renderJavascript (Javascript b) = toLazyByteString b
@@ -127,7 +127,7 @@
 
 contentToJavascript :: Name -> Content -> Q Exp
 contentToJavascript _ (ContentRaw s') = do
-    let d = S8.unpack $ BSU.fromString s'
+    let d = charsToOctets s'
     ts <- [|Javascript . fromByteString . S8.pack|]
     return $ ts `AppE` LitE (StringL d)
 contentToJavascript _ (ContentVar d) = do
@@ -156,7 +156,7 @@
 
 juliusFile :: FilePath -> Q Exp
 juliusFile fp = do
-    contents <- fmap BSU.toString $ qRunIO $ S8.readFile fp
+    contents <- fmap bsToChars $ qRunIO $ S8.readFile fp
     juliusFromString contents
 
 data VarType = VTPlain | VTUrl | VTUrlParam | VTMixin
@@ -186,7 +186,7 @@
 
 juliusFileDebug :: FilePath -> Q Exp
 juliusFileDebug fp = do
-    s <- fmap BSU.toString $ qRunIO $ S8.readFile fp
+    s <- fmap bsToChars $ qRunIO $ S8.readFile fp
     let a = either (error . show) id $ parse parseContents s s
         b = concatMap getVars a
     c <- mapM vtToExp b
@@ -195,7 +195,7 @@
 
 juliusRuntime :: FilePath -> [(Deref, JDData url)] -> Julius url
 juliusRuntime fp cd render' = unsafePerformIO $ do
-    s <- fmap BSU.toString $ qRunIO $ S8.readFile fp
+    s <- fmap bsToChars $ qRunIO $ S8.readFile fp
     let a = either (error . show) id $ parse parseContents s s
     return $ mconcat $ map go a
   where
diff --git a/Text/Utf8.hs b/Text/Utf8.hs
new file mode 100644
--- /dev/null
+++ b/Text/Utf8.hs
@@ -0,0 +1,23 @@
+module Text.Utf8
+    ( charsToOctets
+    , bsToChars
+    , lbsToChars
+    ) where
+
+import qualified Data.ByteString as S
+import qualified Data.ByteString.Lazy.Char8 as L
+
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+
+import qualified Data.Text.Lazy as LT
+import qualified Data.Text.Lazy.Encoding as LT
+
+charsToOctets :: String -> String
+charsToOctets = L.unpack . LT.encodeUtf8 . LT.pack
+
+bsToChars :: S.ByteString -> String
+bsToChars = T.unpack . T.decodeUtf8
+
+lbsToChars :: L.ByteString -> String
+lbsToChars = LT.unpack . LT.decodeUtf8
diff --git a/hamlet.cabal b/hamlet.cabal
--- a/hamlet.cabal
+++ b/hamlet.cabal
@@ -1,5 +1,5 @@
 name:            hamlet
-version:         0.5.1
+version:         0.5.1.1
 license:         BSD3
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>
@@ -41,12 +41,11 @@
 library
     build-depends:   base             >= 4       && < 5
                    , bytestring       >= 0.9     && < 0.10
-                   , utf8-string      >= 0.3.4   && < 0.4
                    , template-haskell
                    , blaze-builder    >= 0.1     && < 0.2
-                   , neither          >= 0.0.1   && < 0.1
                    , parsec           >= 2       && < 4
                    , failure          >= 0.1.0   && < 0.2
+                   , text             >= 0.7     && < 0.10
     exposed-modules: Text.Hamlet
                      Text.Hamlet.RT
                      Text.Cassius
@@ -54,6 +53,7 @@
     other-modules:   Text.Hamlet.Parse
                      Text.Hamlet.Quasi
                      Text.Hamlet.Debug
+                     Text.Utf8
     ghc-options:     -Wall
 
 executable             runtests
diff --git a/runtests.hs b/runtests.hs
--- a/runtests.hs
+++ b/runtests.hs
@@ -7,8 +7,8 @@
 import Text.Hamlet
 import Text.Cassius
 import Text.Julius
-import Data.ByteString.Lazy.UTF8 (toString)
 import Data.List (intercalate)
+import Text.Utf8
 
 main :: IO ()
 main = defaultMain [testSuite]
@@ -148,7 +148,7 @@
 helper :: String -> Hamlet Url -> Assertion
 helper res h = do
     let x = renderHamlet render h
-    res @=? toString x
+    res @=? lbsToChars x
 
 caseEmpty :: Assertion
 caseEmpty = helper "" [$hamlet||]
@@ -450,7 +450,7 @@
 helper' :: String -> Html -> Assertion
 helper' res h = do
     let x = renderHtml h
-    res @=? toString x
+    res @=? lbsToChars x
 
 caseHamlet' :: Assertion
 caseHamlet' = do
@@ -515,7 +515,7 @@
             , (["false"], HDBool False)
             ]
     rend <- renderHamletRT rt scope render
-    toString (renderHtml rend) @?=
+    lbsToChars (renderHtml rend) @?=
         "foo<bar>baz bin 123justnothingvarurlaburl?foo=bar"
 
 caseHamletFileDebugChange :: Assertion
@@ -558,7 +558,7 @@
 celper :: String -> Cassius Url -> Assertion
 celper res h = do
     let x = renderCassius render h
-    res @=? toString x
+    res @=? lbsToChars x
 
 mixin :: CassiusMixin a
 mixin = [$cassiusMixin|
@@ -623,7 +623,7 @@
 jelper :: String -> Julius Url -> Assertion
 jelper res h = do
     let x = renderJulius render h
-    res @=? toString x
+    res @=? lbsToChars x
 
 caseJulius :: Assertion
 caseJulius = do
