Build Status Code Climate Test Coverage

Munge is a static site generator aiming to simplify complex build rules.

It's built partially to emulate unix pipes and scripts; small transformations can be joined, composed, and applied to create almost any site you can think up.

SemVer will be followed once 1.0.0 is released. Until then, the API should be considered experimental.


  • No DSL
  • No metaprogramming
  • LiveReload
  • Optional frontmatter
  • Suitable for large, complex sites (e.g., multiple blogs with different templates, a single blog with multiple data sources)
  • Very configurable
  • Concise rule definition
  • Rules defined by iterating through arrays and modifying matching objects


  • Not yet optimized (Pull requests welcome, gradual optimizations preferred)
  • User facing API has mostly stabilized, but plugins have yet to be fully worked out


Add this line to your application's Gemfile:

gem "munge"

And then execute:

$ bundle

Or install it yourself as:

$ gem install munge


After installing your gem, you can start a project using the command line client.

munge init path/to/project  # create a barebones project
cd path/to/project
munge server                # starts auto-compiling dev server http://localhost:7000/
munge build                 # compiles your project for production
munge view                  # preview production build on http://localhost:7000/

The three main files of your application are config.yml, data.yml, and rules.rb.

Here's an example rules.rb for a blog.

# home page
  .select { |item| == "home" }      # looks for items where path is "src/home.*"
  .each   { |item| item.route = "" }        # sets output file to "/index.html"
  .each   { |item| item.layout = "default"} # sets layout to "layouts/default.*"
  .each   { |item| item[:title] = "home" }  # sets additional frontmatter variables
  .each   { |item| item.transform(:tilt) }  # have Tilt compile this file

# blog posts
  .select { |item| item.relpath?("posts") }               # looks for items in "src/posts/**/*"
  .each   { |item| item.route = "blog/#{item.basename}" } # sets output file to "/blog/#{basename}/index.html"
  .each   { |item| item.layout = "post" }
  .each   { |item| item.transform }                       # sets transform to Tilt (default)

# blog index
posts_for_index =
    .select  { |item| item.route?("blog") }
    .sort_by { |item| item.route }

app.create("blog/index.html.erb", "", posts: posts_for_index)
  .each { |item| item.route = "blog" }
  .each { |item| item.layout = "list" }
  .each { |item| item.transform }



Bug reports and pull requests are welcome on GitHub at

Please open an issue before creating a pull request to discuss whether any new feature should be included as part of the core library or as an external plugin.


The gem is available as open source under the terms of the MIT License.