Haskell bindings for Datastar.
Server-side SDK for building real-time hypermedia applications with Datastar. Stream HTML fragments, reactive signal updates, and scripts to the browser over server-sent events (SSE). Built on WAI so it works with Warp, Scotty, Servant, Yesod, and any other WAI-compatible framework.

Datastar Haskell SDK
A Haskell implementation of the Datastar SDK for building real-time hypermedia applications with server-sent events (SSE).
Live examples: https://hamalainen.dev
License
This package is licensed for free under the MIT License.
Design
The SDK is built on WAI (Web Application Interface), Haskell's standard interface for HTTP servers. This means it works with any WAI-compatible server (Warp, etc.) and any framework built on WAI (Yesod, Scotty, Servant, etc.) without framework-specific adapters.
Key design decisions:
- Minimal dependencies -- the library depends only on
aeson,bytestring,http-types,text, andwai. - WAI streaming -- SSE responses use WAI's native
responseStream, giving you aServerSentEventGeneratorcallback withsendPatchElements,sendPatchSignals, andsendExecuteScript. - No routing opinion -- the SDK provides request helpers (
readSignals,isDatastarRequest) but doesn't impose a routing framework. The examples use simple pattern matching on(requestMethod, pathInfo).
API Overview
import Hypermedia.Datastar
-- Create an SSE response
sseResponse :: DatastarLogger -> (ServerSentEventGenerator -> IO ()) -> Response
-- Send events
sendPatchElements :: ServerSentEventGenerator -> PatchElements -> IO ()
sendPatchSignals :: ServerSentEventGenerator -> PatchSignals -> IO ()
sendExecuteScript :: ServerSentEventGenerator -> ExecuteScript -> IO ()
-- Read signals from a request (query string for GET, body for POST)
readSignals :: FromJSON a => Request -> IO (Either String a)
Quick Start
Add datastar-hs to your build-depends, then:
import Hypermedia.Datastar
import Network.Wai
import Network.Wai.Handler.Warp qualified as Warp
app :: Application
app req respond =
case (requestMethod req, pathInfo req) of
("GET", ["hello"]) -> do
Right signals <- readSignals req
respond $ sseResponse nullLogger $ \gen -> do
sendPatchElements gen (patchElements "<div id=\"message\">Hello!</div>")
_ ->
respond $ responseLBS status404 [] "Not found"
main :: IO ()
main = Warp.run 3000 app