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
Route
type 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 anIsRoute
instance, so we derive it vianewtype
. -
In Add Routes, you will see how to write more elaborate route types and derive
IsRoute
for them.IsRoute
is what tells Ema that a Haskell type is a route type (with URL encoders and decoders).
-
The unit type,
-
The
EmaSite
typeclass defines the “site pipeline” – the input Model type and the output Asset:-
siteOutput
renders this route. -
siteInput
returns 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.runSite
takes a route type (viaTypeApplications
), and runs the Ema site.
-
-
Running the resultant executable without arguments runs the Live Server, whereas running it with the
gen
subcommand will generate the static site (see CLI).
Next, we will explain how to write a simple mood tracker in Ema.