diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+The following license covers this documentation, and the source code, except
+where otherwise indicated.
+
+Copyright 2009, Michael Snoyman. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* 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 "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 HOLDERS 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/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,8 @@
+#!/usr/bin/env runhaskell
+
+> module Main where
+> import Distribution.Simple
+> import System.Cmd (system)
+
+> main :: IO ()
+> main = defaultMain
diff --git a/Text/Shakespeare.hs b/Text/Shakespeare.hs
new file mode 100644
--- /dev/null
+++ b/Text/Shakespeare.hs
@@ -0,0 +1,214 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# OPTIONS_GHC -fno-warn-missing-fields #-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
+-- | For lack of a better name... a parameterized version of Julius.
+module Text.Shakespeare
+    ( ShakespeareSettings (..)
+    , defaultShakespeareSettings
+    , shakespeare
+    , shakespeareFile
+    , shakespeareFileDebug
+    -- * low-level
+    , shakespeareFromString
+    , RenderUrl
+    ) where
+
+import Text.ParserCombinators.Parsec hiding (Line)
+import Language.Haskell.TH.Quote (QuasiQuoter (..))
+import Language.Haskell.TH.Syntax
+import Language.Haskell.TH.Syntax.Internals
+import Data.Text.Lazy.Builder (Builder, fromText)
+import Data.Monoid
+import System.IO.Unsafe (unsafePerformIO)
+import qualified Data.Text as TS
+import qualified Data.Text.Lazy as TL
+import Text.Shakespeare.Base
+
+-- move to Shakespeare?
+readFileQ :: FilePath -> Q [Char]
+readFileQ fp = do
+    qRunIO $ readFileUtf8 fp
+
+-- move to Shakespeare?
+readFileUtf8 :: FilePath -> IO String
+readFileUtf8 fp = fmap TL.unpack $ readUtf8File fp
+
+data ShakespeareSettings = ShakespeareSettings
+    { varChar :: Char
+    , urlChar :: Char
+    , intChar :: Char
+    , toBuilder :: Exp
+    , wrap :: Exp
+    , unwrap :: Exp
+    , justVarInterpolation :: Bool
+    }
+defaultShakespeareSettings :: ShakespeareSettings
+defaultShakespeareSettings = ShakespeareSettings {
+    varChar = '#'
+  , urlChar = '@'
+  , intChar = '^'
+  , justVarInterpolation = False
+}
+
+
+instance Lift ShakespeareSettings where
+    lift (ShakespeareSettings x1 x2 x3 x4 x5 x6 x7) =
+        [|ShakespeareSettings
+            $(lift x1) $(lift x2) $(lift x3)
+            $(liftExp x4) $(liftExp x5) $(liftExp x6) $(lift x7)|]
+      where
+        liftExp (VarE n) = [|VarE $(liftName n)|]
+        liftExp (ConE n) = [|ConE $(liftName n)|]
+        liftExp _ = error "liftExp only supports VarE and ConE"
+        liftName (Name (OccName a) b) = [|Name (OccName $(lift a)) $(liftFlavour b)|]
+        liftFlavour NameS = [|NameS|]
+        liftFlavour (NameQ (ModName a)) = [|NameQ (ModName $(lift a))|]
+        liftFlavour (NameU _) = error "liftFlavour NameU" -- [|NameU $(lift $ fromIntegral a)|]
+        liftFlavour (NameL _) = error "liftFlavour NameL" -- [|NameU $(lift $ fromIntegral a)|]
+        liftFlavour (NameG ns (PkgName p) (ModName m)) = [|NameG $(liftNS ns) (PkgName $(lift p)) (ModName $(lift m))|]
+        liftNS VarName = [|VarName|]
+        liftNS DataName = [|DataName|]
+
+type QueryParameters = [(TS.Text, TS.Text)]
+type RenderUrl url = (url -> QueryParameters -> TS.Text)
+type Shakespeare url = RenderUrl url -> Builder
+
+data Content = ContentRaw String
+             | ContentVar Deref
+             | ContentUrl Deref
+             | ContentUrlParam Deref
+             | ContentMix Deref
+    deriving (Show, Eq)
+type Contents = [Content]
+
+contentFromString :: ShakespeareSettings -> (String -> [Content])
+contentFromString rs s = do
+    compressContents $ either (error . show) id $ parse (parseContents rs) s s
+  where
+    compressContents :: Contents -> Contents
+    compressContents [] = []
+    compressContents (ContentRaw x:ContentRaw y:z) =
+        compressContents $ ContentRaw (x ++ y) : z
+    compressContents (x:y) = x : compressContents y
+
+parseContents :: ShakespeareSettings -> Parser Contents
+parseContents = many1 . parseContent
+  where
+    parseContent :: ShakespeareSettings -> Parser Content
+    parseContent ShakespeareSettings {..} =
+        parseHash' <|> parseAt' <|> parseCaret' <|> parseChar
+      where
+        parseHash' = either ContentRaw ContentVar `fmap` parseVar varChar
+        parseAt' =
+            either ContentRaw go `fmap` parseUrl urlChar '?'
+          where
+            go (d, False) = ContentUrl d
+            go (d, True) = ContentUrlParam d
+        parseCaret' = either ContentRaw ContentMix `fmap` parseInt intChar
+        parseChar = ContentRaw `fmap` (many1 $ noneOf [varChar, urlChar, intChar])
+
+contentsToShakespeare :: ShakespeareSettings -> [Content] -> Q Exp
+contentsToShakespeare rs a = do
+    r <- newName "_render"
+    c <- mapM (contentToBuilder r) a
+    compiledTemplate <- case c of
+        []  -> [|mempty|]
+        [x] -> return x
+        _   -> do
+              mc <- [|mconcat|]
+              return $ mc `AppE` ListE c
+    if justVarInterpolation rs
+      then return compiledTemplate
+      else return $ LamE [VarP r] compiledTemplate
+      where
+        contentToBuilder :: Name -> Content -> Q Exp
+        contentToBuilder _ (ContentRaw s') = do
+            ts <- [|fromText . TS.pack|]
+            return $ (wrap rs) `AppE` (ts `AppE` LitE (StringL s'))
+        contentToBuilder _ (ContentVar d) = do
+            return $ (wrap rs) `AppE` ((toBuilder rs) `AppE` derefToExp [] d)
+        contentToBuilder r (ContentUrl d) = do
+            ts <- [|fromText|]
+            return $ (wrap rs) `AppE` (ts `AppE` (VarE r `AppE` derefToExp [] d `AppE` ListE []))
+        contentToBuilder r (ContentUrlParam d) = do
+            ts <- [|fromText|]
+            up <- [|\r' (u, p) -> r' u p|]
+            return $ (wrap rs) `AppE` (ts `AppE` (up `AppE` VarE r `AppE` derefToExp [] d))
+        contentToBuilder r (ContentMix d) = do
+            return $ derefToExp [] d `AppE` VarE r
+
+shakespeare :: ShakespeareSettings -> QuasiQuoter
+shakespeare r = QuasiQuoter { quoteExp = shakespeareFromString r }
+
+shakespeareFromString :: ShakespeareSettings -> String -> Q Exp
+shakespeareFromString r s = do
+    contentsToShakespeare r $ contentFromString r s
+
+shakespeareFile :: ShakespeareSettings -> FilePath -> Q Exp
+shakespeareFile r fp = readFileQ fp >>= shakespeareFromString r
+
+data VarType = VTPlain | VTUrl | VTUrlParam | VTMixin
+
+getVars :: Content -> [(Deref, VarType)]
+getVars ContentRaw{} = []
+getVars (ContentVar d) = [(d, VTPlain)]
+getVars (ContentUrl d) = [(d, VTUrl)]
+getVars (ContentUrlParam d) = [(d, VTUrlParam)]
+getVars (ContentMix d) = [(d, VTMixin)]
+
+data VarExp url = EPlain Builder
+                | EUrl url
+                | EUrlParam (url, [(TS.Text, TS.Text)])
+                | EMixin (Shakespeare url)
+
+shakespeareFileDebug :: ShakespeareSettings -> FilePath -> Q Exp
+shakespeareFileDebug rs fp = do
+    s <- readFileQ fp
+    let b = concatMap getVars $ contentFromString rs s
+    c <- mapM vtToExp b
+    rt <- [|shakespeareRuntime|]
+    wrap' <- [|\x -> $(return $ wrap rs) . x|]
+    r' <- lift rs
+    return $ wrap' `AppE` (rt `AppE` r' `AppE` (LitE $ StringL fp) `AppE` ListE c)
+  where
+    vtToExp :: (Deref, VarType) -> Q Exp
+    vtToExp (d, vt) = do
+        d' <- lift d
+        c' <- c vt
+        return $ TupE [d', c' `AppE` derefToExp [] d]
+      where
+        c :: VarType -> Q Exp
+        c VTPlain = [|EPlain . $(return $ toBuilder rs)|]
+        c VTUrl = [|EUrl|]
+        c VTUrlParam = [|EUrlParam|]
+        c VTMixin = [|\x -> EMixin $ \r -> $(return $ unwrap rs) $ x r|]
+
+
+shakespeareRuntime :: ShakespeareSettings -> FilePath -> [(Deref, VarExp url)] -> Shakespeare url
+shakespeareRuntime rs fp cd render' = unsafePerformIO $ do
+    s <- readFileUtf8 fp
+    return $ mconcat $ map go $ contentFromString rs s
+  where
+    go :: Content -> Builder
+    go (ContentRaw s) = fromText $ TS.pack s
+    go (ContentVar d) =
+        case lookup d cd of
+            Just (EPlain s) -> s
+            _ -> error $ show d ++ ": expected EPlain"
+    go (ContentUrl d) =
+        case lookup d cd of
+            Just (EUrl u) -> fromText $ render' u []
+            _ -> error $ show d ++ ": expected EUrl"
+    go (ContentUrlParam d) =
+        case lookup d cd of
+            Just (EUrlParam (u, p)) ->
+                fromText $ render' u p
+            _ -> error $ show d ++ ": expected EUrlParam"
+    go (ContentMix d) =
+        case lookup d cd of
+            Just (EMixin m) -> m render'
+            _ -> error $ show d ++ ": expected EMixin"
diff --git a/Text/Shakespeare/Base.hs b/Text/Shakespeare/Base.hs
new file mode 100644
--- /dev/null
+++ b/Text/Shakespeare/Base.hs
@@ -0,0 +1,225 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE CPP #-}
+-- | General parsers, functions and datatypes for all Shakespeare languages.
+module Text.Shakespeare.Base
+    ( Deref (..)
+    , Ident (..)
+    , Scope
+    , parseDeref
+    , parseHash
+    , parseVar
+    , parseAt
+    , parseUrl
+    , parseCaret
+    , parseUnder
+    , parseInt
+    , derefToExp
+    , flattenDeref
+    , readUtf8File
+    ) where
+
+import Language.Haskell.TH.Syntax
+import Language.Haskell.TH (appE)
+import Data.Char (isUpper)
+import Text.ParserCombinators.Parsec
+import Data.List (intercalate)
+import Data.Ratio (Ratio, numerator, denominator, (%))
+import Data.Data (Data)
+import Data.Typeable (Typeable)
+import qualified Data.Text.Lazy as TL
+import qualified System.IO as SIO
+import qualified Data.Text.Lazy.IO as TIO
+
+newtype Ident = Ident String
+    deriving (Show, Eq, Read, Data, Typeable)
+
+type Scope = [(Ident, Exp)]
+
+data Deref = DerefModulesIdent [String] Ident
+           | DerefIdent Ident
+           | DerefIntegral Integer
+           | DerefRational Rational
+           | DerefString String
+           | DerefBranch Deref Deref
+    deriving (Show, Eq, Read, Data, Typeable)
+
+instance Lift Ident where
+    lift (Ident s) = [|Ident|] `appE` lift s
+instance Lift Deref where
+    lift (DerefModulesIdent v s) = do
+        dl <- [|DerefModulesIdent|]
+        v' <- lift v
+        s' <- lift s
+        return $ dl `AppE` v' `AppE` s'
+    lift (DerefIdent s) = do
+        dl <- [|DerefIdent|]
+        s' <- lift s
+        return $ dl `AppE` s'
+    lift (DerefBranch x y) = do
+        x' <- lift x
+        y' <- lift y
+        db <- [|DerefBranch|]
+        return $ db `AppE` x' `AppE` y'
+    lift (DerefIntegral i) = [|DerefIntegral|] `appE` lift i
+    lift (DerefRational r) = do
+        n <- lift $ numerator r
+        d <- lift $ denominator r
+        per <- [|(%) :: Int -> Int -> Ratio Int|]
+        dr <- [|DerefRational|]
+        return $ dr `AppE` (InfixE (Just n) per (Just d))
+    lift (DerefString s) = [|DerefString|] `appE` lift s
+
+parseDeref :: Parser Deref
+parseDeref = do
+    skipMany $ oneOf " \t"
+    x <- derefSingle
+    res <- deref' $ (:) x
+    skipMany $ oneOf " \t"
+    return res
+  where
+    delim = (many1 (char ' ') >> return())
+            <|> lookAhead (char '(' >> return ())
+    derefOp = try $ do
+        _ <- char '('
+        x <- many1 $ noneOf " \t\n\r()"
+        _ <- char ')'
+        return $ DerefIdent $ Ident x
+    derefParens = between (char '(') (char ')') parseDeref
+    derefSingle = derefOp <|> derefParens <|> numeric <|> strLit<|> ident
+    deref' lhs =
+        dollar <|> derefSingle'
+               <|> return (foldl1 DerefBranch $ lhs [])
+      where
+        dollar = do
+            _ <- try $ delim >> char '$'
+            rhs <- parseDeref
+            let lhs' = foldl1 DerefBranch $ lhs []
+            return $ DerefBranch lhs' rhs
+        derefSingle' = do
+            x <- try $ delim >> derefSingle
+            deref' $ lhs . (:) x
+    numeric = do
+        n <- (char '-' >> return "-") <|> return ""
+        x <- many1 digit
+        y <- (char '.' >> fmap Just (many1 digit)) <|> return Nothing
+        return $ case y of
+            Nothing -> DerefIntegral $ read' "Integral" $ n ++ x
+            Just z -> DerefRational $ toRational
+                       (read' "Rational" $ n ++ x ++ '.' : z :: Double)
+    strLit = do
+        _ <- char '"'
+        chars <- many quotedChar
+        _ <- char '"'
+        return $ DerefString chars
+    quotedChar = (char '\\' >> escapedChar) <|> noneOf "\""
+    escapedChar =
+        (char 'n' >> return '\n') <|>
+        (char 'r' >> return '\r') <|>
+        (char 'b' >> return '\b') <|>
+        (char 't' >> return '\t') <|>
+        (char '\\' >> return '\\') <|>
+        (char '"' >> return '"') <|>
+        (char '\'' >> return '\'')
+    ident = do
+        mods <- many modul
+        func <- many1 (alphaNum <|> char '_' <|> char '\'')
+        let func' = Ident func
+        return $
+            if null mods
+                then DerefIdent func'
+                else DerefModulesIdent mods func'
+    modul = try $ do
+        c <- upper
+        cs <- many (alphaNum <|> char '_')
+        _ <- char '.'
+        return $ c : cs
+
+read' :: Read a => String -> String -> a
+read' t s =
+    case reads s of
+        (x, _):_ -> x
+        [] -> error $ t ++ " read failed: " ++ s
+
+expType :: Ident -> Name -> Exp
+expType (Ident (c:_)) = if isUpper c || c == ':' then ConE else VarE
+expType (Ident "") = error "Bad Ident"
+
+derefToExp :: Scope -> Deref -> Exp
+derefToExp s (DerefBranch x y) = derefToExp s x `AppE` derefToExp s y
+derefToExp _ (DerefModulesIdent mods i@(Ident s)) =
+    expType i $ Name (mkOccName s) (NameQ $ mkModName $ intercalate "." mods)
+derefToExp scope (DerefIdent i@(Ident s)) =
+    case lookup i scope of
+        Just e -> e
+        Nothing -> expType i $ mkName s
+derefToExp _ (DerefIntegral i) = LitE $ IntegerL i
+derefToExp _ (DerefRational r) = LitE $ RationalL r
+derefToExp _ (DerefString s) = LitE $ StringL s
+
+-- FIXME shouldn't we use something besides a list here?
+flattenDeref :: Deref -> Maybe [String]
+flattenDeref (DerefIdent (Ident x)) = Just [x]
+flattenDeref (DerefBranch (DerefIdent (Ident x)) y) = do
+    y' <- flattenDeref y
+    Just $ y' ++ [x]
+flattenDeref _ = Nothing
+
+parseHash :: Parser (Either String Deref)
+parseHash = parseVar '#'
+
+parseVar :: Char -> Parser (Either String Deref)
+parseVar c = do
+    _ <- char c
+    (char '\\' >> return (Left [c])) <|> (do
+        _ <- char '{'
+        deref <- parseDeref
+        _ <- char '}'
+        return $ Right deref) <|> (do
+            -- Check for hash just before newline
+            _ <- lookAhead (oneOf "\r\n" >> return ()) <|> eof
+            return $ Left ""
+            ) <|> return (Left [c])
+
+parseAt :: Parser (Either String (Deref, Bool))
+parseAt = parseUrl '@' '?'
+
+parseUrl :: Char -> Char -> Parser (Either String (Deref, Bool))
+parseUrl c d = do
+    _ <- char c
+    (char '\\' >> return (Left [c])) <|> (do
+        x <- (char d >> return True) <|> return False
+        (do
+            _ <- char '{'
+            deref <- parseDeref
+            _ <- char '}'
+            return $ Right (deref, x))
+                <|> return (Left $ if x then [c, d] else [c]))
+
+parseCaret :: Parser (Either String Deref)
+parseCaret = parseInt '^'
+
+parseInt :: Char -> Parser (Either String Deref)
+parseInt c = do
+    _ <- char c
+    (char '\\' >> return (Left [c])) <|> (do
+        _ <- char '{'
+        deref <- parseDeref
+        _ <- char '}'
+        return $ Right deref) <|> return (Left [c])
+
+parseUnder :: Parser (Either String Deref)
+parseUnder = do
+    _ <- char '_'
+    (char '\\' >> return (Left "_")) <|> (do
+        _ <- char '{'
+        deref <- parseDeref
+        _ <- char '}'
+        return $ Right deref) <|> return (Left "_")
+
+readUtf8File :: FilePath -> IO TL.Text
+readUtf8File fp = do
+    h <- SIO.openFile fp SIO.ReadMode
+    SIO.hSetEncoding h SIO.utf8_bom
+    TIO.hGetContents h
diff --git a/shakespeare.cabal b/shakespeare.cabal
new file mode 100644
--- /dev/null
+++ b/shakespeare.cabal
@@ -0,0 +1,41 @@
+name:            shakespeare
+version:         0.10.0
+license:         BSD3
+license-file:    LICENSE
+author:          Michael Snoyman <michael@snoyman.com>
+maintainer:      Michael Snoyman <michael@snoyman.com>
+synopsis:        A toolkit for making compile-time interpolated templates
+description:
+    Shakespeare is a template family for type-safe, efficient templates with simple variable interpolation . Shakespeare templates can be used inline with a quasi-quoter or in an external file. Shakespeare interpolates variables according to the type being inserted.
+    .
+    Note there is no dependency on haskell-src-extras.
+    .
+    packages that use this: shakespeare-js, shakespeare-css, shakespeare-interpolated, hamlet, and xml-hamlet
+    Please see the documentation at <http://docs.yesodweb.com/book/hamlet/> for more details.
+
+category:        Web, Yesod
+stability:       Stable
+cabal-version:   >= 1.8
+build-type:      Simple
+homepage:        http://www.yesodweb.com/book/templates
+
+library
+    build-depends:   base             >= 4       && < 5
+                   , bytestring       >= 0.9     && < 0.10
+                   , template-haskell
+                   , blaze-html       >= 0.4     && < 0.5
+                   , parsec           >= 2       && < 4
+                   , failure          >= 0.1     && < 0.2
+                   , text             >= 0.7     && < 0.12
+                   , containers       >= 0.2     && < 0.5
+                   , blaze-builder    >= 0.2     && < 0.4
+                   , process          >= 1.0     && < 1.2
+    exposed-modules: 
+                     Text.Shakespeare
+                     Text.Shakespeare.Base
+    ghc-options:     -Wall
+
+
+source-repository head
+  type:     git
+  location: git://github.com/yesodweb/hamlet.git
