Rendering HTML

Once you have model and routes in place and constrained, the last piece of the puzzle is to write a function that takes both as arguments and returns file content (lazy bytestring, to be exact) to generate. This function can be as simple as the following:

render :: MyModel -> Route -> Asset ByteString
render model route =
  AssetGenerated Html "<b>Hello</b>, world!"

The AssetGenerated Html tells Ema that you are generating HTML content, which will be appropriately handled by the Hot Reload of the live server.

Of course we want it to be real, by using our model value, as well as generate the HTML based on the route. We will also use the blaze-html library to make writing HTML in Haskell palatable (see also the layout helper). A more realistic starting point (if not the finishing product) would be:

render :: MyModel -> Route -> Asset ByteString 
render model route = AssetGenerated Html . Blaze.renderHtml $ 
  H.html $ do 
    H.head $ do 
      H.title "My site"
      H.base ! A.href "/"  -- This is important
    H.body $ do 
      H.h1 "My site"
      case route of 
        Index -> 
          H.h1 "Welcome to my website!"
          H.p $ do 
            "Checkout the"
            H.a ! A.href (H.toValue $ Ema.routeUrl About) $ "About"
            " page."
        About ->
          H.div $ H.p "This website is managed by yours truly"
      H.footer $ do 
        A.a ! A.href "https://github.com/user/repo" $ "Source on GitHub"

Note that Ema provides a routeUrl helper function that serializes your route to the final URL (here, /about) for linking to. There is also a routeUrlWith function which allows you to disable pretty URLs, to get back the .html suffix for deployments to traditional web servers like Nginx, Gitlab, etc.

Spend a few moments trying to appreciate how this is much simpler to write than dealing with HTML template files spread across the disk as is the case with traditional static site generators. If you choose to go the DSL route, Haskell’s type-safety now applies to your HTML as well. On top of it, Ema’s hot reload will instantly update the dev server’s browser view whenever you change your HTML (or any of the Haskell source code).

Of course when using Ema nothing prevents you from choosing to use traditional HTML templates, and you can get hot reload on them too with a little bit of plumbing.

Next, you might want to peruse the helper topics if you need some extra functionality provided.

Links to this page