Blaaargh-0.3: A simple filesystem-based content management system for HappstackSource codeContentsIndex

"Blaaargh!" is a simple filesystem-based content management system for static or semi-static publishing. You can run it standalone (...or will be able to soon) or integrate it as a component in a larger happstack application.

Like the venerable blosxom ( package, Blaaargh! relies on plain-text files on the file system as its content database.


  • simple on-disk content database
  • posts/pages written in markdown format
  • pages formatted into HTML by a flexible cascading template system based on HStringTemplate ( Page templates can be overridden on a per-page or per-folder basis.
  • directories can be given indices using the templating system. Various views of the directory contents (e.g. N most recent pages, pages in forward/reverse chronological order, pages in alphabetical order) are exposed to the index templates.
  • directories with defined indices get Atom-format syndication feeds
  • configuration parameters (site title, site URL, base URL, etc.) specified in an INI-style config file


  • a web-accessible "administrative area"
  • a comment system (for my homepage I'm currently just outsourcing this to Disqus)


The Blaaargh directory consists of the following contents:

an INI-style configuration file
a tree of .st template files, served by HStringTemplate
a tree of content files. Markdown-formatted files (with .md extensions) are parsed and read as "posts" that are rendered to HTML via the templating mechanism. Other files are served as static content.

Let's say you have some files in here:


Think of it like this -- you request content, either a single post, a directory, or an atom feed (hardcoded as /[dir]/feed.xml). Blaaargh searches for the closest matching template.

For .md files ("posts" or "pages"), the templates cascade: e.g. for a file content/foo/bar/, we would search templates/ for the following templates, in order:

  • foo/bar/
  • foo/bar/
  • foo/

For directories, the templates don't cascade; a directory needs to have a matching template in order to be served. E.g. for a directory /foo/bar/quux, we search templates/ for "foo/bar/quux/", and if content/foo/bar/quux/ exists, we read it into the template as content text. (More about this in "TEMPLATING" below.)


A Blaaargh! config file looks like this:

 # what's the domain name?
 siteurl =

 # blaaargh content will be served at this base URL
 baseurl = /foo

 # site title
 title    = Example dot com
 # authors
 authors  = John Smith <>
 # Atom icon
 icon     = /static/icon.png

 # posts on this list (or directories containing posts) won't be included in
 # directory indices, nor in atom feeds
 skipurls = static

Blaaargh! uses the ConfigFile library for configuration and post header parsing. (


Posts are (mostly) in Markdown format, with the exception of a key-value header prefixed by pipe (|) characters. Example:

 | title: Example post
 | author: John Smith <>
 | published: 2009-09-15T21:18:00-0400
 | summary: A short summary of the post contents
 This is an example post in *markdown* format.

Blaaargh! accepts the following key-values for posts:

The title of the post
The post's author
same as author
a summary of the post
the post's last update time in RFC3339 format
the post's publish date in RFC3339 format

The headers are parsed as follows: any lines starting with the | character (up until the first line not starting with |) have the prefix stripped and are sent through ConfigFile.

Please see its haddock for input syntax.


The documents get indexed into a key-value mapping by id. (Where an "id" for a post is defined as its relative path from content/, with the .md suffix removed.)

Files with an '.md' suffix are treated as "posts"/"pages", and are expected to be in markdown format. Files with other suffices are served as static files.


Blaaargh! uses templates to present the content of posts and lists of posts in HTML.

For an individual post (either postname-specific or generic, Blaaargh exports a template variable called $post$ which is a map containing the following attributes:


So in other words, within your template the post's URL can be accessed using $$.

For directory templates (, we collect the posts within that directory and present them to the templating system as a list of post objects (i.e. containing the $id$/$date$/etc. fields listed above):

    $recentPosts$                -- N.B. 5 most recent posts
initBlaaargh :: FilePath -> IO BlaaarghState
serveBlaaargh :: BlaaarghHandler
runBlaaarghHandler :: BlaaarghState -> ServerPartT BlaaarghMonad a -> ServerPartT IO a
addExtraTemplateArguments :: ToSElem a => [(String, a)] -> BlaaarghMonad ()
data BlaaarghException
blaaarghExceptionMsg :: BlaaarghException -> String
data BlaaarghMonad a
type BlaaarghHandler = ServerPartT BlaaarghMonad Response
data BlaaarghState
:: FilePathpath to blaaargh directory
-> IO BlaaarghState
Initialize a Blaaargh instance. Given the name of a directory on the disk, initBlaaargh searches it for configuration, content, and template files, and produces a finished BlaaarghState value. Throws a BlaaarghException if there was an error reading the state.
serveBlaaargh :: BlaaarghHandlerSource
The top-level happstack handler. The BlaaarghHandler is a ServerPartT over a state monad; you "run" this handler by feeding it a BlaaarghState using runBlaaarghHandler. It handles requests on its base url (defined in the {blaaargh_dir}/config file) and serves up content from the content area.
=> BlaaarghStateblaaargh state, obtained from calling initBlaaargh
-> ServerPartT BlaaarghMonad aa blaaargh handler
-> ServerPartT IO a
Given Blaaargh state and a happstack ServerPartT over a BlaaarghMonad, runBlaaarghHandler produces a ServerPartT over IO that you can pass to happstack.
addExtraTemplateArguments :: ToSElem a => [(String, a)] -> BlaaarghMonad ()Source

Sometimes you want to pass extra key-value mappings to be served in Blaaargh templates. For example:

lift (addExtraTemplateArguments [("foo", "foovalue")]) >> serveBlaaargh

will cause the value $foo$ to be expanded as "foovalue" within templates served by Blaaargh.

data BlaaarghException Source
BlaaarghException is the exception type thrown when Blaaargh encounters an error.
show/hide Instances
blaaarghExceptionMsg :: BlaaarghException -> StringSource
Obtain the error message from a BlaaarghException
data BlaaarghMonad a Source
A BlaaarghMonad is a state monad over IO.
show/hide Instances
type BlaaarghHandler = ServerPartT BlaaarghMonad ResponseSource
The ServerPartT happstack handler type is a monad transformer; here we define BlaaarghHandler as a ServerPartT around our BlaaarghMonad type.
data BlaaarghState Source
BlaaarghState is an opaque data type that holds Blaaargh internal state.
show/hide Instances
Produced by Haddock version 2.4.2