This post is very old and contains obsolete information.
I make a lot of websites, and I have a certain toolkit that I use to build them. The most useful things I use are:
- layouts and partials so I only need to set things up once
hamlfor writing html, since I don’t like closing tags
sassfor writing css
Markdownfor formatting large blogs of content
Middleman is written in Ruby, so it’s our familiar toolset, and unlike Jekyll it uses Sprockets, which is the same asset pipelining system that Rails uses. So you get all the benefits of using a robust system that works for Rails apps without having to learn a bunch more things.
In the node world Yeoman does something similar, but I personally have had poor luck getting Grunt to work reliably in practice.
Setting up a simple static site with Middleman
One of the problems with starting with Middleman is that there are so many places to start. Lets look at how to setup a basic middleman site with bootstrap-sass, haml, and bower. First thing is to install middleman:
And create an app:
This creates 4 files in the main directory,
Gemfile.lock, which we know and love,
config.rb which configures how middleman generates the site, and
source which are the sourcefiles of the site.
middleman installs the
middleman-livereload plugin, so in development mode any browers that have a page open with refresh when you save a file. This makes testing a lot easier. We can install other gems here to add different functionality. Let’s add a few of these now:
The first two gems expand the functionality of middleman, one to add tasks to push the final site build to
gh-pages and a whole bunch more, and the second to make it easier to build
The file two are including
bootstrap-sass – the same that we use for rails sites – and
jquery. These get included into the sprockets asset path, so you don’t need to maintain them in your project. (We’ll also see below how to integrate
bower components into your project.)
config.rb is where we configure how middleman itself works.
Lets go through this in detail.
page "CNAME", layout: false says to move the file called
CNAME over without wrapping in the main layout. Since this file doesn’t have .html in the name, it would otherwise get ignored. This file is for having a custom domain on Github Pages, if that’s the sort of thing you are in to.
set commands are there to configure different middleman settings, here to show where the various stylesheet, image, and css directories are.
activate :directory_indexes with enable pretty urls. Directory indexes means that files named
about.html will actually get generated into a file called
/about/index.html, and will rely on the underlying server to have
/about actually show the directory “index” page, making the urls prettier. This doesn’t work on all servers but works on most of them. This plugin will actually rewrite the output of the
link_to tags, so you don’t need to adjust your templates to work.
activate :bootstrap_navbar is an extension that we added in the Gemfile, which makes it easier to generate bootstrap navbars. Extensions generally work in three ways: they add helper methods, they change the way that the sitemap is processed, or they add different commands to the “middleman” command.
We see an example of that at the bottom of the
config.rb file, where we configure the
This also takes some configuration, and in this case it set to deploy to github pages, and to make sure that it generates the site before doing so. Here is the middleman-deploy github page with documentation.
There are two sections that each configure a different middleman environment. The first is used when you run
middleman server to look at the site locally:
The final section is configuring the
build process, when you run
middleman build and it creates the generated files in the
The basic way to use bower is to put this in
And then you can put things in your
all.js file like
To get all of the assets that are included in the packge, you may need to specify the package in the
config.rb file, such as:
More information on the Middleman Asset Pipline documentation
Using layouts and partials
source directory is where the actual code for your site lives. Here is an example
layouts/layout.haml file to give you a sense of how to use layouts and include partials:
In this usage, this is similar to the way that rails layouts work. I’m using the
~ HAML operator inside of
= here because I want to make sure that it doesn’t do anything wonky with the indention on
<pre> blocks, btw.
Middleman has a concept of nested layouts, which lets you have wrap an a layout around another one. I think that this is confusing in practice, but as an example you could have a
layouts/sidebar_layout.erb that looked like:
<% wrap_layout :layout do %> <div class="sidebar"> <%= partial "layouts/sidebar" %> </div> <div class="content"> <%= yield %> </div> <% end %>
The YAML preable the preyaml
Metadata about the template is included in a block of text at the top of the file, which gets pulled off to set things that the templating system can use later. On the top of this file that I am editing right now, it looks like this
--- title: 'Building Sites with Middleman' subtitle: 'lean publishing' tags: middleman, ruby, howto header_image: books.jpg --- I make a lot of websites, and I have a certain toolkit that I use to build...
header_image attributues are available in the templates as page data, so you can access them like:
%h1= current_article.title %h2= current_article.data['subtitle']
title is built into middleman, subtitle and header image are just some random things I made up. The
tags attribute is part of the
middleman-blog extension which we will cover below.
How the build works
When you run
middleman server or
middleman build, middleman loads up the configuration file in
config.rb. It creates a sitemap based upon the files in the
source directory as well as other directives inside of the config.rb file.
By default it only includes files like
.js, but you can set it manually include a non-template file (like our
page "CNAME" above or create other
proxy files. Proxy files are a way of seperating out the templates from the source data.
This creates three entries into the sitemap called
/about/harry.html that use a specific template.
This data doesn’t need to be hardcoded into the
config.rb btw, you can also place
yml files in the
data/ directory which middleman will load automatically. For example,
And then in your
config.rb you could access this as:
Then each entry in the sitemap the file is processed (based upon the extension, so scss -> js, haml -> html, etc.) into the build directory. Helper methods are available inside of the templates for things like
image_tag and all of the rest.
Starting the server in preview mode will start a local server on port
4567 that generates the files on demand. If you have livereload enabled this will automatically trigger a page refresh for any open browsers, so you can tweak and look at things as you go.
Inside of your templates,
config.environment == :development when you are in preview mode. So, if there are some things that you don’t want to push to the live site but are useful for development, you can switch them on and off using that mechanism.
This does basically the same thing as the server, but the templates are generally further processed. Cachebusting can be enabled, and you can include tracking code if
config.environment == :build is true. This goes through all of the files in source that look like webfiles and places them in the
And easy way to check out what you have there is by
cding into the
build/ directory and running a simple webserver to serve the pages. Relative links don’t work when you open the file directly in the browser, so you need to use an actual webserver.
And then open a new browser on port
In the basic
:git setting that we have above, middleman deploy will build the site into the
build/ directory, switch that directory to the
gh-pages branch, and push it to
origin. Assuming that you are hosting your repo on github, this will publish the static content on github pages.
If you want to use a custom domain then you need to create a
CNAME file in
source/ with the domain name, and set up your DNS records to match.
One thing to note is that while changes to the pages seem to deploy quickly, it takes a long time for the first push to github pages to show up, on the order of 10-15 minutes.
More information on middleman-deploy.
Building a blog
There are two good extensions for building a blog with middleman. The default template for blog is sort of confusing in the way that it’s laid out, mainly because it gets rid of the
layouts/ directory, but let’s go through it and see how it’s supposed to work:
Now we have another middleman site, with a bunch of files. It also creates a new command:
Let’s also include the
middleman-blog-drafts gem into the
activate :drafts in `config.rb, and that will give us a few more commands:
This lets us keep drafts in git and doesn’t force us to commit to a date until we are ready to publish it. There are
date attributes that the default blog extension knows about to turn it on and off, and is a good example of something that you can see in development but not production, but that still leaves to moving files around manually to adjust the date.
What does it add
In addition to the sitemap, we now have a
tag concept inside of the middleman app. Articles are represented as pages (by default using
markdown) but the
calendar templates are actually more like
proxy templates than file templates, and when the site is generated middleman will iterate over then to produce many output files from one template.
Part of the
index.html.haml of this site looks like:
- (drafts + page_articles).each do |article| .post .post-date - unless article.is_a? ::Middleman::Blog::Drafts::DraftArticle %p= article.date.strftime( '%b %e' ) - else %p.draft Draft
I’m putting all of the articles in a list, both drafts and published ones, and only showing the date for articles which have already been published.
Here’s what gets added to the
This should be enough to get you started, and more documentation is here . At this point it really becomes a design and development challenge, not figuring out how to use the tool.
Go get started
Middleman gives you all of the front-end developer benefits of using a system like Rails, but outputs static content than can be served anywhere without any dependancies. Many sites don’t really require all that for them to run, and it’s crazy to me that something as read heavy as a blog often can’t perform well under load given that it’s just serving up the same old stuff over and over again. You want to have some tooling to make it easier, but it doesn’t need to be run time tooling.
Image Credit: Moyan Brenn