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:
-
The
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 anIsRouteinstance, so we derive it vianewtype. -
In Add Routes, you will see how to write more elaborate route types and derive
IsRoutefor them.IsRouteis what tells Ema that a Haskell type is a route type (with URL encoders and decoders).
-
The unit type,
-
The
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 (viaTypeApplications), 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.