diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for reflex-dom-th
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,44 @@
+# reflex-dom-th
+Do you develop for the web? And you know functional reactive programming is the way to go. So you must use Reflex-DOM.
+But how can you integrate all these HTML snippet, which you found. You are tired in converting everything to to el, elAttr' etc, right?
+
+From this day on this reflex-dom-th library will automate the task of converting your HTML templates to Reflex-Dom.
+
+# Examples
+
+The basic example
+
+    [dom|<div>hello</div>|]
+
+is equivalent to
+
+    el "div" $ text "hello"
+
+You can also put the html in a external file and include it with
+
+    $(domFile "template.html")
+
+It it possible to have multiple elements and attributes
+
+    [dom|<ul class="list">
+          <li>Item1</div>
+	  <li>Item1</div>
+	</ul> |]
+
+Dynamic content can be injected two curly braces
+
+        [dom|<ul class="list">
+          <li>{{item1}}</div>
+	  <li>{{item2}}</div>
+	</ul> |]
+	   where item1, item2 :: MonadWidget t m =>  m ()
+	         item1 = text "Item1"
+		 item2 = text "Item2"
+
+
+To bind events to the elements it is possible to extract get the elements as a result. The reference number is the position in the result tuple.
+
+    (li1, li2, ul) <- [dom|<ul #2 class="list">
+    	       	             <li #0>Item1</div>
+	  		     <li #1>Item1</div>
+			   </ul> |]
diff --git a/reflex-dom-th.cabal b/reflex-dom-th.cabal
new file mode 100644
--- /dev/null
+++ b/reflex-dom-th.cabal
@@ -0,0 +1,82 @@
+cabal-version:      2.4
+name:               reflex-dom-th
+version:            0.1.0.0
+
+-- A short (one-line) description of the package.
+synopsis: reflex-dom-th transpiles HTML templates to haskell code for @reflex-dom@
+
+-- A longer description of the package.
+description:
+      Reflex-DOM is a very powerful web framework for functional reactive programming (FRP).
+      Web pages itself are written in HTML.
+      .
+      @reflex-dom-th@ combines the power of these two techniques by transpiling HTML templates to Haskell for the @reflex-dom@ library.
+      
+        
+Stability: Experimental
+-- A URL where users can report bugs.
+bug-reports: https://github.com/chrbauer/reflex-dom-th/issues
+
+license: BSD-3-Clause
+author:             Christoph Bauer
+maintainer:         mail@christoph-bauer.net
+
+-- A copyright notice.
+-- copyright:
+category: FRP, Web, GUI, HTML, Javascript, Reactive, Reactivity, User Interfaces, User-interface
+extra-source-files: CHANGELOG.md, README.md
+
+library
+  build-depends:
+                  base
+                , megaparsec  
+  exposed-modules:
+          Reflex.Dom.TH.Parser
+        , Reflex.Dom.TH
+  default-extensions: TemplateHaskell, TupleSections, DeriveLift, RecordWildCards, QuasiQuotes, OverloadedStrings
+  build-depends:
+              base >= 4 && < 5
+            , array
+            , containers
+            , megaparsec
+            , reflex-dom-core
+            , template-haskell
+            , text
+  ghc-options: -Wall -fwarn-tabs
+  hs-source-dirs:   src
+  default-language: Haskell2010
+
+
+test-suite test-reflex-dom-th
+  default-language:
+    Haskell2010
+  type:
+    exitcode-stdio-1.0
+  hs-source-dirs:
+    tests
+  main-is:
+    test.hs
+  build-depends:
+            base >= 4 && < 5
+          , bytestring
+          , filepath
+          , megaparsec
+          , hspec
+          , reflex-dom-th
+          , stm >= 2.5.0.2
+          , tasty
+          , tasty-golden
+          , tasty-hspec
+          --, hspec-megaparsec
+
+                    
+          --, tasty-hspec
+          
+-- executable ref-dom-th-example
+--   hs-source-dirs: example
+--   main-is: Main.hs
+--   build-depends:
+--       base >= 4 && < 5
+--     , reflex-dom
+
+    
diff --git a/src/Reflex/Dom/TH.hs b/src/Reflex/Dom/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Reflex/Dom/TH.hs
@@ -0,0 +1,121 @@
+-- | 
+
+module Reflex.Dom.TH
+  (dom, domFile, merge)
+where
+
+
+import Text.Megaparsec.Error
+
+import Language.Haskell.TH.Quote
+import Language.Haskell.TH
+import Language.Haskell.TH.Syntax
+
+import Reflex.Dom.TH.Parser
+import Reflex.Dom.Widget.Basic 
+import qualified Data.Map as M
+import Data.Map (Map)
+--import Data.Maybe
+import Data.List (insert)
+import Data.Text (Text)
+import qualified Data.Text as T
+import Data.Array
+
+type Ref = Int
+data CElement = CElement { cTag :: String
+                         , cSiblingsRefs :: [Ref]
+                         , cChildRefs :: [Ref]
+                         , cOutRefs :: [Ref]
+                         , cMyRef :: Maybe Ref
+                         , cAttrs :: [(String, String)]
+                         , cChilds :: [CElement] }
+               | CText String
+               | CComment String
+               | CWidget String
+               deriving Show
+
+merge :: Ord a => [a] -> [a] -> [a]
+merge a [] = a
+merge [] b = b
+merge  a@(ah:at) b@(bh:bt)
+  | compare ah bh == GT = bh : merge a bt
+  | otherwise = ah : merge at b
+
+
+--  do (r1, (r1a, r1b)) <- el1 $ el1a >>= \ r1a -> el1b >>= \r1b -> return (r1a, r1b)
+
+
+
+compile :: [TElement] -> [CElement] -> [Ref] -> ([CElement], [Ref])
+compile [] acc inRefs = (reverse acc, inRefs)
+compile ((TElement {..}):etail) acc inRefs =
+      compile etail (elem':acc) expRefs
+  where
+    elem' = CElement tTag inRefs childRefs outRefs tRef attrs childs
+    (childs, childRefs) = compile tChilds [] []
+    outRefs = maybe id insert tRef childRefs
+    expRefs = merge inRefs outRefs
+    attrs = [ (k, v) | (Static, k, v) <- tAttrs ]
+compile (elem:etail) acc inRefs =
+      compile etail (toC elem : acc) inRefs
+  where
+    toC (TText text) = CText text
+    toC (TComment comment) = CComment comment
+    toC (TWidget widget) = CWidget widget
+    toC _ = undefined
+                           
+
+
+opt :: (Ref -> Name) -> Maybe Ref -> Q Pat
+opt var = maybe (runQ [p| () |]) $ varP . var
+
+clambda var Nothing crefs   =  lamE [tupP $ map (varP . var) crefs ]
+clambda var mref crefs =  lamE [tupP [ opt var mref
+                           , tupP $ map (varP . var) crefs]]
+
+
+cnodes :: (Ref -> Name) -> [CElement] ->  ExpQ
+cnodes _ []  = [| blank |]
+cnodes var [elem@(CElement _ _ crefs orefs mref _ _)]  
+    | null orefs = [| $(cnode var elem) |]
+    | otherwise = [| $(cnode var elem) >>=  $(clambda var mref crefs                                                                                        (appE (varE 'return) (tupE $ map (varE . var) orefs))) |]
+cnodes var (elem@(CElement _ _ crefs orefs mref _ _):rest)  = [| $(cnode var elem) >>=  $(clambda var mref crefs (cnodes var rest)) |]
+                                                         
+cnodes  var [elem] = cnode var elem
+cnodes var (h:t)  = [|  $(cnode var h) >> $(cnodes var t) |]
+
+cnode :: (Ref -> Name) -> CElement -> ExpQ
+cnode var (CElement tag _ _ _ Nothing attr childs) = [|  elAttr tag (M.fromList attr) $(cnodes var childs)|]
+cnode var (CElement tag _ _ _ (Just _) attr childs) = [|  elAttr' tag (M.fromList attr) $(cnodes var childs) |]
+cnode _ (CText "") = [| blank |]
+cnode _ (CText txt) = [| text txt |]
+cnode _ (CWidget x) = unboundVarE $ mkName x
+cnode _ (CComment txt) = [| comment txt |]
+
+domExp :: [TElement] -> Q Exp
+domExp result =
+  let (cns, out) = compile result [] [] in do
+    varNames <-  listArray (0, length out) <$> mapM (\ r -> newName ("r" ++ show r)) out
+    cnodes (varNames !) cns
+
+dom :: QuasiQuoter
+dom = QuasiQuoter
+  { quoteExp  = \str ->
+      case parseTemplate "" str of
+        Left err -> fail $ errorBundlePretty err
+        Right result -> domExp result
+  , quotePat  = error "Usage as a parttern is not supported"
+  , quoteType = error "Usage as a type is not supported"
+  , quoteDec = error "Usage as a decl is not supported"
+
+  }
+
+
+domFile :: FilePath -> Q Exp
+domFile path = do
+  str <- runIO (readFile path)
+  addDependentFile path
+  case parseTemplate path str of
+        Left err -> fail $ errorBundlePretty err
+        Right result  ->  domExp result
+  
diff --git a/src/Reflex/Dom/TH/Parser.hs b/src/Reflex/Dom/TH/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Reflex/Dom/TH/Parser.hs
@@ -0,0 +1,92 @@
+-- | 
+
+module Reflex.Dom.TH.Parser
+( TElement(..),
+  AttributeType(..),
+  parseTemplate
+  )
+where
+
+import Data.Char
+import Data.List
+
+
+import Text.Megaparsec
+import Text.Megaparsec.Char
+import qualified Text.Megaparsec.Char.Lexer as L 
+import Data.Void
+import Control.Monad
+import Language.Haskell.TH.Syntax
+
+type Parser = Parsec Void String
+type TTag = String
+data AttributeType = Static | Dynamic deriving (Show, Lift)
+type Attribute = (AttributeType, String, String)
+type Ref = Int
+data TElement = TElement { tTag :: TTag
+                         , tRef :: Maybe Ref
+                         , tAttrs :: [Attribute]
+                         , tChilds :: [TElement] }
+               | TText String
+               | TComment String
+               | TWidget String
+               deriving Show
+
+
+openTag :: Parser (String, Maybe Int, [Attribute])
+openTag =  
+     between (char '<') (char '>') $ do
+       tag <- many (alphaNumChar <|> char '-')
+       space
+       ref <-  optional $ do
+         void $ char '#'
+         L.decimal <* space
+       attrs <- attributes
+       space
+       return (tag, ref, attrs)
+
+closeTag :: String -> Parser ()
+closeTag tag = void $ between (string "</") (space >> char '>') (string tag)
+
+comment :: Parser TElement
+comment = TComment <$> ((string "<!--") *> (manyTill anySingle (string "-->")))
+
+
+stringLiteral :: Parser String
+stringLiteral = char '\"' *> manyTill L.charLiteral (char '\"')
+
+attribute :: Parser Attribute
+attribute = (Static,,) <$>  (some alphaNumChar <* char '=') <*> stringLiteral
+
+
+attributes :: Parser [Attribute]
+attributes = sepBy attribute space1 <* space
+                     
+
+node :: Parser TElement
+node = do
+  (tag, ref, attrs) <- openTag
+  space
+  childs <- manyTill element (closeTag tag)
+  return $ TElement tag ref attrs childs
+
+
+widget :: Parser TElement
+widget =  TWidget <$> (string "{{" *> manyTill anySingle (string "}}"))
+
+text :: Parser TElement
+text =  TText <$>  dropWhileEnd isSpace <$> some (satisfy (/= '<'))
+
+element :: Parser TElement     
+element = (comment <|>  node <|> widget <|> text) <* space
+  
+template :: Parser [TElement]
+template = do
+  space
+  result <- many element
+  eof
+  return result
+
+
+parseTemplate :: FilePath -> String -> Either (ParseErrorBundle String Void) [TElement]
+parseTemplate fn = runParser template fn
diff --git a/tests/test.hs b/tests/test.hs
new file mode 100644
--- /dev/null
+++ b/tests/test.hs
@@ -0,0 +1,30 @@
+import Test.Tasty (defaultMain, TestTree, testGroup)
+import Test.Tasty.Golden (goldenVsString, findByExtension)
+import System.IO (readFile)
+import Reflex.Dom.TH.Parser
+import System.FilePath (takeBaseName, replaceExtension)
+import qualified Data.ByteString.Lazy as LBS
+import qualified Data.ByteString.Lazy.Char8 as L
+import Text.Megaparsec
+
+main :: IO ()
+main = defaultMain =<< goldenTests
+
+
+templateToAst :: String -> LBS.ByteString -> LBS.ByteString
+templateToAst  path = L.pack . render . parseTemplate path .  L.unpack
+  where render (Right x) = show x
+        render (Left err) = errorBundlePretty err
+  
+
+goldenTests :: IO TestTree
+goldenTests = do
+  htmlFiles <- findByExtension [".html"] "."
+  return $ testGroup "Html Template Parser golden tests"
+    [ goldenVsString
+        (takeBaseName htmlFile) 
+        astFile
+        (templateToAst htmlFile  <$> LBS.readFile htmlFile) 
+    | htmlFile <- htmlFiles
+    , let astFile  = replaceExtension htmlFile ".ast"
+    ]
