If your static site is generated depending on local files on disk, the general flow of things is as follows:
runEma render $ \model -> do -- Load everything on launch initialModel <- loadFilesAndBuildModel LVar.set model initialModel -- Continue to monitor and update the model observeFileSystem $ \action -> LVar.modify model $ applyAction action
For monitoring local files on disk you would typically use something like fsnotify in place of
observeFileSystem. What is the point of doing this? To support hot reload on data change. Imagine that your static site is generated based on Markdown files as well as HTML templates on disk. If either the Markdown file, or a HTML template file is modified, we want the web browser to hot reload the updated HTML instantly. This is enabled by storing both these kinds of files in the application model and using LVar to update it over time.
For filesystem changes, Ema provides a helper based on
fsnotify in the
Ema.Helper.FileSystem module. You can use it as follows
import qualified Ema.Helper.FileSystem as FileSystem type Model = Map FilePath Text Ema.runEma render $ \model -> do LVar.set model =<< do mdFiles <- FileSystem.filesMatching "." ["**/*.md"] forM mdFiles readFileText <&> Map.fromList FileSystem.onChange "." $ \fp -> \case FileSystem.Update -> when (takeExtension fp == ".md") $ do log $ "Update: " <> fp s <- readFileText fp LVar.modify model $ Map.insert fp s FileSystem.Delete -> whenJust (takeExtension fp == ".md") $ do log $ "Delete: " <> fp LVar.modify model $ Map.delete fp
In most cases, however, you probably want to use the higher level function
mountOnLVar. It “mounts” the files you specify onto the model LVar such that any changes to them are automatically reflected in your model value.
Ema.runEma render $ \model -> do FileSystem.mountOnLVar "." ["**/*.md"] model $ \fp -> \case FileSystem.Update -> do s <- readFileText fp pure $ Map.insert fp s FileSystem.Delete -> pure $ Map.delete fp