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.

Taking the blog site example from Example route, our model would look something like the following:

data Model = Model 
  { modelSiteTitle :: Text 
  , modelBlogPosts :: Map Slug (Date, Pandoc)

The idea here is that in order to render our weblog, we only need a value of type Model, and we can render it without reading anything from the environment (doing IO).

Models impact two places:

  • RouteModel of IsRoute associates a route type with a model type. This enables Route Prism (and routeUniverse) to accept that model value as an argument.
  • In EmaSite typeclass, siteInput can now return this model value (and it can be time-varying if using a Dynamic), as well as siteOutput can take the model value so as to render the site based on it.

Useful libraries

  • ixset-typed - for database-like querying into in-memory model values
  • unionmount - mounting local files into Haskell in-memory model with change updates.
Links to this page
  • unionmount

    unionmount is a Haskell library that wraps fsnotify to provide a Dynamic-friendly API to listen on filesystem changes and update an in-memory Model type. The library interface is such that you can “mount” multiple directories (union'ing them in the process), and have it update the model when files on any of those directories change.

  • Live Server

    The “run” command of CLI runs the live-server, as opposed to the “gen” command which generates the static site one off. The live-server is a simple HTTP server that serves the Ema site “on the fly” (without doing O(n) static-site generation). Furthermore, changes to your Model type (via Dynamic) will automatically Hot Reload the browser clients to display the new HTML as rendered using the new model value.

  • IsRoute
    RouteModel is (optionally) used to specify the value that is used for encoding routes (as defined by routePrism).
  • Hot Reload

    For anything outside of the Haskell code, your code becomes responsible for monitoring and updating the Model type Dynamic. The unionmount library already provides utilities to facilitate this for monitoring changes to files and directories.

  • Hello World
    The EmaSite typeclass defines the “site pipeline” – the input Model type and the output Asset:
    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.
  • Guide
  • EmaSite

    The siteInput method takes a SiteArg value (and other relevant parameters) and returns a Dynamic of the site’s Model type.

    The siteOutput method takes the Model type value snapshot at that point in time, as well as the route value to render and returns a Asset output (typically HTML bytestring) for it. siteOutput has IO capabilities; usually it is defined as a pure function (siteOutput ... = pure <expr>) inasmuch as all the data required to render the site is contained in the Model type, but sometimes you may need IO (example).

  • Dynamic

    The EmaSite’s siteInput method returns a Dynamic of Model type, which represents all the data required to render a site. If you do not want Hot Reload, you may return a pure value.

  • Composing Ema apps

    Ema.Route.Lib.Extra.StaticRoute provides a StaticRoute site that can monitor a directory and allow referring to the files in it. The Model type for this sub-route keeps track of last-added time, which gets appended to the URL when running in Live Server, which in turn has the effect of “refreshing” the target content (eg: image) when the underlying files change.

  • Add a Model

    To generate our mood tracker view, we need … mood data, i.e., the mood Model type. If we are recording our mood each day, then Haskell’s Map type is one way to represent moods over time.

  • Add Routes
    We don’t need any special Model type to encode a Day route, thus RouteModel is a unit. But we’ll modify this in next step (to implement routeUniverse).
    RouteModel: associate a value type (Model type) that will be used for encoding and decoding routes (see next point)