Route type

Algebraic datatypes (ADT) are well suited to define website routes in Haskell. For example, the following type represents routes in a particular weblog site:

Example route
-- An example of nested routes
-- Route's expected encoding is given as a comment.

data Route
  = Route_Index          -- index.html
  | Route_About          -- about.html
  | Route_Contact        -- contact.html
  | Route_Blog BlogRoute -- blog/<BlogRoute>

data BlogRoute
  = BlogRoute_Index      -- index.html
  | BlogRoute_Post Slug  -- post/<Slug>

newtype Slug = Slug { unSlug :: String }

As you can see, routes can be nested. BlogRoute is a subroute of the Route type. When encoding Route, it can delegate to the encoder for BlogRoute (inductively).

Routes are central to Ema apps

An Ema app is defined by its route type. All routes must be an instance of the IsRoute class, which provides a route encoder (see Route Prism) that is used to convert to and from the corresponding .html filepaths. This instance can be hand-written or derived generically.

Links to this page
  • Model type

    A “model”, in an Ema app, represents all the data used to render the site. The model is also used (in IsRoute), optionally, to encode the route types.

  • Hello World
    a Route type type corresponding to the generated HTML file(s), as well as
  • Guide
    Define your site Route type as Haskell ADTs:
  • EmaSite

    The EmaSite typeclass “orchestrates” and ties-together the whole site pipeline. The instance is written on the top-level site Route type, which in turn enables using the Ema.runSite function to run the site from main entrypoint of your Haskell project.

  • Composing Ema apps

    The composition happens via sub-route composition. i.e., the Route type of your larger Ema app can contain the sub-route type in its sum constructors. If the sub-routes have IsRoute and EmaSite instances, then the corresponding instances for the larger route can be defined in terms of them.

  • Add Routes

    See Route type for details.

    The first step is to think about the various pages and define their corresponding route types. Since our application will have an index page (displaying mood summary) and pages specific to the individual days, we will use an ADT with two constructors: