Writing an Ema apps involves two things at a minimum:
- a Route type type corresponding to the generated HTML file(s), as well as
- an EmaSite instance on that route type defining the site render pipeline.
The simplest Ema app is presented below:
import Ema -- The Route type of our site newtype Route = Route () deriving newtype (Show, Eq, Ord, Generic, IsRoute) -- Site pipeline (input & output) instance EmaSite Route where siteInput _ _ = -- There is no input in a hello-world site pure $ pure () siteOutput _ _ _ = -- The output of index.html is simply a hello-world message in HTML pure $ Ema.AssetGenerated Ema.Html "<b>Hello</b>, Ema" main :: IO () main = -- Hook everything up in main using runSite. void $ Ema.runSite @Route ()
Let’s walk through this code:
Routetype represents the pages on our site. As there is only one page (
index.html) in our hello-world site, we simply use
The unit type,
(), already has an
IsRouteinstance, so we derive it via
In Add Routes, you will see how to write more elaborate route types and derive
IsRouteis what tells Ema that a Haskell type is a route type (with URL encoders and decoders).
- The unit type,
EmaSitetypeclass defines the “site pipeline” – the input Model type and the output Asset:
siteOutputrenders this route.
siteInputreturns the model used in rendering the routes. In Add a Model we will use a custom model, and in Dynamic Model we will make it time-varying.
Ema.runSitetakes a route type (via
TypeApplications), and runs the Ema site.
Running the resultant executable without arguments runs the Live Server, whereas running it with the
gensubcommand will generate the static site (see CLI).
Next, we will explain how to write a simple mood tracker in Ema.