diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for blaze-htmx
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2022, Tobias Brandt
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. 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.
+
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 HOLDER OR CONTRIBUTORS 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.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/blaze-htmx.cabal b/blaze-htmx.cabal
new file mode 100644
--- /dev/null
+++ b/blaze-htmx.cabal
@@ -0,0 +1,40 @@
+cabal-version:       >=1.10
+-- Initial package description 'blaze-htmx.cabal' generated by 'cabal
+-- init'.  For further documentation, see
+-- http://haskell.org/cabal/users-guide/
+
+name:                blaze-htmx
+version:             0.1.0.0
+synopsis: Blaze integration of the htmx library
+description: Blaze integration of the htmx library including WS and SSE extensions
+-- bug-reports:
+license: 	     BSD3
+license-file:        LICENSE
+author:              Tobias Brandt
+maintainer:          tobbra91@gmail.com
+Homepage:            https://github.com/TobiasB91/blaze-htmx
+copyright:	     Tobias Brandt
+category:	     Text, Web
+build-type:          Simple
+extra-source-files:  CHANGELOG.md
+
+library
+  exposed-modules:     Text.Blaze.Htmx
+                     , Text.Blaze.Htmx.WebSockets
+                     , Text.Blaze.Htmx.ServerSentEvents
+  build-depends:       base >=4 && < 5
+                     , blaze-html >= 0.8 && < 1
+                     , blaze-markup >= 0.8 && < 0.9
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+
+
+test-suite main
+  main-is:             Main.hs
+  type:                exitcode-stdio-1.0
+  build-depends:       base
+                     , blaze-html
+                     , blaze-htmx 
+  hs-source-dirs:      test
+  default-language:    Haskell2010
+  ghc-options:         -Wall
diff --git a/src/Text/Blaze/Htmx.hs b/src/Text/Blaze/Htmx.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Blaze/Htmx.hs
@@ -0,0 +1,144 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Text.Blaze.Htmx where
+
+import Text.Blaze.Internal (attribute, Attribute, AttributeValue)
+
+
+hxBoost_ :: AttributeValue -> Attribute
+hxBoost_ = attribute "hx-boost" " hx-boost=\""
+{-# INLINE hxBoost_ #-}
+
+hxBoost :: Attribute
+hxBoost = hxBoost_ "true"
+{-# INLINE hxBoost #-}
+
+hxConfirm :: AttributeValue -> Attribute
+hxConfirm = attribute "hx-confirm" " hx-confirm=\""
+{-# INLINE hxConfirm #-}
+
+hxDelete :: AttributeValue -> Attribute
+hxDelete = attribute "hx-delete" " hx-delete=\""
+{-# INLINE hxDelete #-}
+
+hxDisable_ :: AttributeValue -> Attribute
+hxDisable_ = attribute "hx-disable" " hx-disable=\""
+{-# INLINE hxDisable_ #-}
+
+hxDisable :: Attribute
+hxDisable = hxDisable_ ""
+{-# INLINE hxDisable #-}
+
+hxDisinherit :: AttributeValue -> Attribute
+hxDisinherit = attribute "hx-disinherit" " hx-disinherit=\""
+{-# INLINE hxDisinherit #-}
+
+hxEncoding_ :: AttributeValue -> Attribute
+hxEncoding_ = attribute "hx-encoding" " hx-encoding=\""
+{-# INLINE hxEncoding_ #-}
+
+hxEncoding :: Attribute
+hxEncoding = hxEncoding_ "multipart/form-data"
+{-# INLINE hxEncoding #-}
+
+hxExt :: AttributeValue -> Attribute
+hxExt = attribute "hx-ext" " hx-ext=\""
+{-# INLINE hxExt #-}
+
+hxGet :: AttributeValue -> Attribute
+hxGet = attribute "hx-get" " hx-get=\""
+{-# INLINE hxGet #-}
+
+hxHeaders :: AttributeValue -> Attribute
+hxHeaders = attribute "hx-headers" " hx-headers=\""
+{-# INLINE hxHeaders #-}
+
+hxHistoryElt_ :: AttributeValue -> Attribute
+hxHistoryElt_ = attribute "hx-history-elt" " hx-history-elt=\""
+{-# INLINE hxHistoryElt_ #-}
+
+hxHistoryElt :: Attribute
+hxHistoryElt = hxHistoryElt_ ""
+{-# INLINE hxHistoryElt #-}
+
+hxInclude :: AttributeValue -> Attribute
+hxInclude = attribute "hx-include" " hx-include=\""
+{-# INLINE hxInclude #-}
+
+hxParams :: AttributeValue -> Attribute
+hxParams = attribute "hx-params" " hx-params=\""
+{-# INLINE hxParams #-}
+
+hxPatch :: AttributeValue -> Attribute
+hxPatch = attribute "hx-patch" " hx-patch=\""
+{-# INLINE hxPatch #-}
+
+hxPost :: AttributeValue -> Attribute
+hxPost = attribute "hx-post" " hx-post=\""
+{-# INLINE hxPost #-}
+
+hxPreserve_ :: AttributeValue -> Attribute
+hxPreserve_ = attribute "hx-preserve" " hx-preserve=\""
+{-# INLINE hxPreserve_ #-}
+
+hxPreserve :: Attribute
+hxPreserve = hxPreserve_ ""
+{-# INLINE hxPreserve #-}
+
+hxPrompt :: AttributeValue -> Attribute
+hxPrompt = attribute "hx-prompt" " hx-prompt=\""
+{-# INLINE hxPrompt #-}
+
+hxPushUrl :: AttributeValue -> Attribute
+hxPushUrl = attribute "hx-push-url" " hx-push-url=\""
+{-# INLINE hxPushUrl #-}
+
+hxPut :: AttributeValue -> Attribute
+hxPut = attribute "hx-put" " hx-put=\""
+{-# INLINE hxPut #-}
+
+hxRequest :: AttributeValue -> Attribute
+hxRequest = attribute "hx-request" " hx-request=\""
+{-# INLINE hxRequest #-}
+
+hxSelect :: AttributeValue -> Attribute
+hxSelect = attribute "hx-select" " hx-select=\""
+{-# INLINE hxSelect #-}
+
+-- | Deprecated. Use "Text.Blaze.Htmx.ServerSentEvents" instead.
+hxSse_ :: AttributeValue -> Attribute
+hxSse_ = attribute "hx-sse" " hx-sse=\""
+{-# INLINE hxSse_#-}
+
+hxSwap :: AttributeValue -> Attribute
+hxSwap = attribute "hx-swap" " hx-swap=\""
+{-# INLINE hxSwap #-}
+
+hxSwapOob :: AttributeValue -> Attribute
+hxSwapOob = attribute "hx-swap-oob" " hx-swap-oob=\""
+{-# INLINE hxSwapOob #-}
+
+hxSync :: AttributeValue -> Attribute
+hxSync = attribute "hx-sync" " hx-sync=\""
+{-# INLINE hxSync #-}
+
+hxTarget :: AttributeValue -> Attribute
+hxTarget = attribute "hx-target" " hx-target=\""
+{-# INLINE hxTarget #-}
+
+hxTrigger :: AttributeValue -> Attribute
+hxTrigger = attribute "hx-trigger" " hx-trigger=\""
+{-# INLINE hxTrigger #-}
+
+hxVals :: AttributeValue -> Attribute
+hxVals = attribute "hx-vals" " hx-vals=\""
+{-# INLINE hxVals #-}
+
+-- | Deprecated. Use 'hxVals'.
+hxVars_ :: AttributeValue -> Attribute
+hxVars_ = attribute "hx-vars" " hx-vars=\""
+{-# INLINE hxVars_ #-}
+
+-- | Deprecated. Use "Text.Blaze.Htmx.WebSockets" instead.
+hxWs_ :: AttributeValue -> Attribute
+hxWs_ = attribute "hx-ws" " hx-ws=\""
+{-# INLINE hxWs_ #-}
diff --git a/src/Text/Blaze/Htmx/ServerSentEvents.hs b/src/Text/Blaze/Htmx/ServerSentEvents.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Blaze/Htmx/ServerSentEvents.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Text.Blaze.Htmx.ServerSentEvents where
+
+import Text.Blaze.Internal (attribute, Attribute, AttributeValue)
+
+sseConnect :: AttributeValue -> Attribute
+sseConnect = attribute "sse-connect" " sse-connect=\""
+{-# INLINE sseConnect #-}
+
+sseSwap :: AttributeValue -> Attribute
+sseSwap = attribute "sse-swap" " sse-swap=\""
+{-# INLINE sseSwap #-}
+
+
diff --git a/src/Text/Blaze/Htmx/WebSockets.hs b/src/Text/Blaze/Htmx/WebSockets.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Blaze/Htmx/WebSockets.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Text.Blaze.Htmx.WebSockets where
+
+import Text.Blaze.Internal (attribute, Attribute, AttributeValue)
+
+wsConnect :: AttributeValue -> Attribute
+wsConnect = attribute "ws-connect" " ws-connect=\""
+{-# INLINE wsConnect #-}
+
+wsSend :: AttributeValue -> Attribute
+wsSend = attribute "ws-send" " ws-send=\""
+{-# INLINE wsSend #-}
+
+
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Text.Blaze.Html.Renderer.Pretty 
+import Text.Blaze.Html5 as H hiding (main)
+import Text.Blaze.Htmx
+
+main :: IO ()
+main = print $ renderHtml testHtml
+
+
+testHtml :: Html 
+testHtml = docTypeHtml $ do
+    H.head $ H.title "some title"
+    body $ do
+        button ! hxConfirm "something to confirm" $ toHtml ("click me" :: String)
+        button ! hxBoost $ toHtml ("or me" :: String)
