The code for a growing collection of very short stories on the web.
Small Stories is built using a custom static site generator written in Haskell. It is modeled in many ways after Yesod.
Why build yet another static site generator? I had a few motivations:
- Most of the other static site generators out there are basically nicer versions of Make. I didn't feel like an input → transform → output approach made much sense for the design I had in mind.1
- I wanted to play around with Yesod but found it unsuitable for static sites (believe me, I tried).
- I'm an intermediate Haskeller and I wanted a project to hack on.
Small Stories uses the Shakespearean templates, just like Yesod. All of the templates are in submodules of
Components are Small Stories's take on Yesod's Widgets. They present a composable, simple abstraction around a small bit of HTML and CSS. Like Yesod's Widgets, components compose cleanly within caret brackets in Hamlet and we offer a
toComponent function and accompanying typeclass that behaves much like Yesod's
The biggest differences from Widgets:
- While Components themselves are monadic in nature, they do not need to be run in any special monad to produce a value. Widgets are tied to Yesod's Handler monad.
Also there is the fact that Small Stories is a static site generator and Yesod is designed to handle individual requests, so Components have a slightly different feel in that respect.
SmallStories.Component module for the implementation.
Much like Yesod, Small Stories compiles all templates and static assests directly into the binary, making it totally relocatable. In the
SmallStories.Static module there is an implementation similar to Yesod's
We provide Template Haskell to embed all files in a particular directory. Note that the files are read at compile time, so the
smallstories binary depends on only the text of the stories as input.
More Architecture Details
Small Stories is as a UNIX executable with a fairly simple set of command line flags. Command line parsing is driven by CmdArgs. The
SmallStories.Main module handles this as well as assembling the pages to output.
For the moment there is a
Page data type which (now) serves little purpose but to hold arguments to be passed to the
fooComponent functions. It will be going away soon, hopefully. The corresponding module is
The other main data type not already discussed above are the routing data type. Like Yesod, Small Stories leverages the Shakespearean templates to provide type safe URLs. This means that there's no way to write a link in a template that's a 404!
SmallStories.Route module itself is not particularly interesting, but do note how the Component type is parameterized over the route type, which should make it highly reusable.
The design came first before I started implementing; I prototyped it in HTML. ↩