
rib
 

Rib is a Haskell library for writing your own static site generator.
How does it compare to Hakyll?
- Use the Shake build system
- Builtin support for using Haskell DSL to define the HTML
(Lucid) & CSS
(Clay) of your site
- Like Hakyll, Rib uses Pandoc for parsing the source
documents
 
- Remain as simple as possible to use (see screenshot below)
- Optional Nix based workflow for easily reproducible environment
Rib prioritizes the use of existing tools over reinventing them, and enables
the user to compose them as they wish instead of having to write code to fit a
custom framework.
Here is how your code may look like if you were to generate your static site
using Rib:

Getting Started
The easiest way to get started with Rib is to use the
template
repository, rib-sample, from Github.
Directory structure
Let's look at what's in the template repository:
$ git clone https://github.com/srid/rib-sample.git mysite
...
$ cd mysite
$ ls -F
a/  b/  default.nix  Main.hs  README.md  rib-sample.cabal
The three key items here are:
- Main.hs: Haskell source containing the DSL of the HTML/CSS of your site.
- a/: The source content (eg: Markdown sources and static files)
- b/: The target directory, initially empty, will contain generated content
(i.e., the HTML files, and copied over static content)
The template repository comes with a few sample posts under a/, and a basic
HTML layout and CSS style defined in Main.hs.
Run the site
Now let's run them all.
Clone the sample repository locally, install Nix and
run your site as follows:
nix-shell --run 'ghcid -T main'
(Note even though the author recommends it Nix is strictly not required; you may
simply run ghcid -T main instead of the above command if you do not wish to
use Nix.)
Running this command gives you a local HTTP server at http://localhost:8080/
(serving the generated files) that automatically reloads when either the content
(a/) or the HTML/CSS/build-actions (Main.hs) changes. Hot reload, in other
words.
How Rib works
How does the aforementioned nix-shell command work?
- 
nix-shellwill run the given command in a shell environment with all of our
dependencies (notably the Haskell ones including theriblibrary itself)
installed.
 
- 
ghcidwill compile yourMain.hsand run itsmainfunction.
 
- 
Main.hs:mainin turn calls the Shake build action (viaRib.App.run)
defined inRib.Simple.buildActionpassing it your functionrenderPage.
 
There is quite a bit going on in that step 3! Let's break it down:
- 
Rib.App.run: this parses the CLI arguments and runs the rib CLI "app" which
can be run in one of a few modes --- generating static files, watching thea/directory for changes, starting HTTP server for theb/directory. By
default---without any explicit arguments---this will run the Shake build
action passed as argument on every file change and spin up a HTTP server.
 
- 
Rib.Simple.buildAction: Therunfunction takes a Shake build action to
run on file change.Rib.Simpleprovides a very simple build action for
generating the most simple static site --- a list of posts with static assets
--- which the sample repository uses.
 
Run that command, and visit http://localhost:8080 to view your site.
Editing workflow
Now try making some changes to the content, say a/first-post.md. You should
see it reflected when you refresh the page. Or change the HTML or CSS of your
site in Main.hs; this will trigger ghcid to rebuild the Haskell source and
restart the server.
What's next?
Great, by now you should have your static site generator ready and running! What
more can you do? Surely you may have specific needs; and this usually translates
to running custom Shake actions during the build.
Rib provides helper functions in Rib.Shake and Rib.Pandoc to make this
easier. Indeed the Rib.Simple.buildAction function which the sample project
readily uses makes use of these functions.
In order to customize your site's build actions,
- 
Copy the source for buildActionfrom theRib.Simplemodule
to yourMain.hs
 
- 
Make any customizations you want in your buildActionfunction. Refer to
Hackage for API docs.
 
- 
Use that as the argument to the Rib.App.runfunction in yourmain
 
Notice how Rib's builtin buildAction is
forward-defined
which adds to the simplicity of the entire thing.
Examples