Heist is an an “xhtml-based templating engine, allowing Haskell functions to be bound to XML tags.” and is suitable for use as a HTML templating Haskell library where you care about using on-disk file templates rather a type-safe DSL. I found its library documentation somewhat lacking in regards to just getting started, so here’s a quick howto.

The most simple use of heist library is a two-stage process.

Load your templates

We interpret them here, but in your application you might want to compile them instead. H.HeistState Identity is the type you would need to keep track of in your application state.

import qualified Heist as H
import qualified Heist.Interpreted as HI

  :: MonadIO m => FilePath -> m (Either [String] (H.HeistState Identity))
loadHeistTemplates templateDir = do
  let heistCfg :: H.HeistConfig Identity =
          & H.hcNamespace .~ ""
          & H.hcTemplateLocations .~ [H.loadTemplates templateDir]
  liftIO $ H.initHeist heistCfg

Render a template

This is the parse when you use your templates to render HTML with a given context (what heist calls “splices”).

import qualified Text.Blaze.Renderer.XmlHtml as RX

  :: ByteString -> Either [String] (H.HeistState Identity) -> LByteString
renderHeistTemplate name etmpl =
  either error id . runExcept $ do
    heist <-
      hoistEither . first (unlines . fmap toText) $ etmpl
      heistWithCtx = 
          & HI.bindString "markdown-title" "Hello world"
          & HI.bindSplice "markdown-html" $ RX.renderHtml ...
    (builder, _mimeType) <-
      tryJust "Unable to render" $
        runIdentity $ HI.renderTemplate heistWithCtx name
    pure $ toLazyByteString builder