Building static websites with Middleman

I’m going to make a bold statement — static sites are cool. Jekyll has been one of the libraries at the core of this movement, which has given rise to static site generators made in nearly every language you can think of. Static websites have the benefit of simplicity; they don’t need complex server-side technologies to host, they just need something that can serve HTML.

The purpose of any static site generator is to take some templates, some content and compile it into some static HTML ready for you to deploy. Middleman is a library for creating static websites written in Ruby, that utilises some of the power of Rails (the popular Ruby web framework). It allows you to build static websites with modern workflows in mind and with a high degree of developer productivity.

In this article we’ll be touching on how Middleman works, some of its features and how you can deploy a Middleman site to various hosting platforms with ease.

Hello, Middleman

First of all, Middleman is a Ruby gem (a packaged Ruby library) so you’ll need Ruby running on your machine (>= 1.9.3 ideally) along with Bundler (A Ruby package management tool). There’s a comprehensive Ruby install guide for Mac here, and for Windows here. Although Middleman is a Ruby library, you won’t need to have an understanding of Ruby to get started. However, if you’d like to learn more about Ruby and it’s (beautiful) syntax use the excellent TryRuby.org site as a starting point.

I’m also going to assume you’re fairly comfortable with a terminal as Middleman requires the command line to run its tasks. However, you won’t need to know much, just how to run some simple commands.

To get started we need to install the Middleman gem. You can read all about what a Gem is and how it works here.

$ gem install middleman

If all has gone well, you should be able to run

$ middleman version

And see something like Middleman 3.1.2 (depending on what the latest version is).

OK, so with Middleman installed we can create a project. To do this (inside the current directory you’re in) run:

$ middleman init boom

Where ‘boom’ is the name of the project (and therefore the name of the folder Middleman puts its files in).

If you change into this directory ($ cd boom) and take a look at the files Middleman has generated you’ll see that its created quite a few files for you. Don’t worry about the Gemfile & Gemfile.lock for now, the main thing you’re interested in is the source folder.

Open up the project in your favourite text editor (mine is Sublime Text 2) and take a look at the contents of the source folder. Before we go any further, it’s important to realise that Middleman uses ERB for templates (hence the .erb extensions). For an introduction to ERB templating, see this article.

So when we ran middleman init it created some default files, including some styles, JavaScript, images and a layout. Well, lets see what this site looks like so far. Middleman has a handy built in server when developing locally without having to run the build step each time. To start the server, switch back to your prompt (inside the project folder) and run:

$ middleman server

You’ll see by the output that Middleman is now running on your local machine and can be accessed by visiting https://localhost:4567. Opening that page you should see the Middleman splash message. The server Middleman starts can be left open whilst you develop your site – the only time you’ll need to restart it is if you add any Gems to the Gemfile. Editing the file, or any of the assets and reloading the browser will display the new change you have made.

Ok so what’s actually happening here? Well, Middleman is compiling the site with the layout in the layout.erb file and then loading in the index.html.erb file into this layout dynamically. Pretty cool. But hang on, none of this is static yet – let’s build our site as it stands and output some plain old HTML. In another tab (or window) of your prompt run the build command:

$ middleman build

This will do the magic to compile your site into HTML, with the assets in their correct folders and all the ERB tags compiled into HTML properties. You can see the result of the compilation in the build folder.

Digging deeper

So now we have the Middleman basics covered (initialising, previewing and building) but there’s a lot more you can do. We’ll go over a few of the more interesting parts of Middleman now, but as always the documentation is your friend.

Creating additional pages

Pages in Middleman are as simple as adding another .html.erb file in the sources folder. So for example we can add a file called about.html.erb with the following content:

<div class="about">
<h1>About us</h1>
</div>

Then by navigating to https://localhost:4567/about.html we’ll see this new page.

Assets

Middleman uses Sprockets, the same asset pipeline as integrated into Rails, which provides a powerful way to embed assets into your sites and even use tools like Sass, LESS and Coffeescript with ease.

Using Sass in Middleman is very straight forward. First of all create a stylesheet with an .css.scss extension. So for this example we’ll use base.css.scss with the following arbitrary example:

@import "normalize";

$bright-highlight: #FF0000;

h1 { color: $bright-highlight; }

Then you’ll need to change the stylesheet_link_tag in the layout.erb file to use the new file. Simply change helper method to include the stylesheet:

<%= stylesheet_link_tag "base" %>

Reloading the site will show the change, with the compiled Sass output. No Sass watchers to setup – just nice and simple.

Similarly, we can use Sprockets to easily concatenate our JavaScript into one file. Sprockets allows for require directives to be added to your files, so in our all.js file we can do the following:

//= require jquery

$(document.body).append($("<h2>Awesome!</h2>"));

(Where jquery is a JavaScript file in our javascripts directory).

Partials

A partial allows us to share content across multiple pages and only define it once. Middleman allows us to use these through the partial method.

A prime use case for this might be a sidebar, which would be saved in the source folder under the name _sidebar.html.erb (partials always start with an underscore)

<aside>
    <h2>About us</h2>
    <p>Herp derp.</p>
</aside>

We’re able to use this sidebar in multiple places by using the tag (in any template):

<%= partial "sidebar" %>

Partials get really cool when you can pass data into them. So let’s augment that previous example for illustration:

<aside class="<%= classes %>">
    <h2>About us</h2>
    <p>Herp derp.</p>
</aside>

We’d then call this with a custom class

<%= partial "sidebar", locals: { classes: "herp derp" } %>

This might look a little bit complicated for those not familiar with Ruby syntax, but essentially locals is a hash of data with key, value pairs (you might recognise it if you’re familiar with JavaScript objects).

Template Helpers

Middleman provides a variety of template helper methods that can be used in your files to speed up some tasks for you. The documentation gives a reference to all of these methods, but we’ll cover a few here.

To link to between our ‘Home’ and ‘About’ pages:

<%= link_to "About", '/about.html' %>

To embed an image:

<%= image_tag "logo.png", "Our logo" %>

(Where logo.png is a file in the images directory)

The content_for helper is a really powerful feature that captures content and allows it to be injected. So for example, we might have a header that has different content on each page. In our layout.erb file we’d have the following:

…
<header class="site-header">
    <h1>Our company</h1>

    <% if content_for?(:header) %>  
    <div class="site-header__content">
            <%= yield_content :header %>
        </div>
    <% end %>
</header>
<div class="site-content">
    <%= yield %>
</div>
…

Then on our homepage we might want it to say ‘Welcome’. We’d do that in our index.html.erb file.

<% content_for :header do %>
    <h2>Welcome</h2>
<% end %>

<p>Rest of our page…</p>

In our about.html.erb file we might want to make it say ‘About’ and have an image:

<% content_for :header do %>
    <h2>About us</h2>
    <%= image_tag "logo_small.png" %>
<% end %>

<p>Rest of our about page…</p>

When we come to run our middleman build command, the content blocks will be populated on the pages as specified. This gives us a powerful way to template our pages and inject content at various points in our layout.

Page variables (Frontmatter)

You’ll notice that we’ve been setting a title: Blah variable at the top of our templates, which you can see being output in the layout.erb file.

<%= current_page.data.title %>

Using this format we can define custom data that can be used from our templates. So from the earlier header example using content_for we could refactor the header title to be output using the data.

In our layout.erb:

 …
<header class="site-header">
    <h1>Our company</h1>

<div class="site-header__content">
        <h2><%= current_page.data.subtitle %></h2>
        <%= yield_content(:header) if content_for?(:header) %>
    </div>
</header>
<div class="site-content">
    <%= yield %>
</div>
…

(Note I used the inline ruby if syntax here for brevity)

Then in our about.html.erb file for example

---
title: About
subtitle: About
---
<% content_for :header do %>
    <%= image_tag "logo_small.png" %>
<% end %>

For more information see the documentation

Project Templates

Project templates allow us to initialise Middleman with a different piece of boilerplate code. This is a great way to save time when starting a new project that uses starting templates like HTML5 Boilerplate or SMACSS.

You can see a full list of templates available at the Middleman site.

To use a project template when initialising Middleman, run the initialise command with the --template= flag.

middleman init boom --template=html5
middleman init boom --template=smacss

Configuring Middleman

Middleman provides a wide range of configuration options within the config.rb file located in the root of your project. Some of the more common options are commented out, but usually what I like to turn on are:

configure :build do
    activate :minify_css
    activate :minify_javascript
    activate :asset_hash
end

These options allow minification of CSS / JS automatically in your build step, along with providing a unique URL for your assets (for cache busting).

You can read more about configuring Middleman and its extensions in the documentation.

Deploying your site

Lastly I wanted to briefly touch on deploying a Middleman site. You have a multitude of options for doing this and really it’s up to you which platform you chose.

Some of the options you have include: S3 / Rackspace / Google Storage, Dropbox, GitHub Pages, Heroku and more traditional servers (via rsync).

Deploying to Heroku

I’m going to briefly show you how to deploy your Middleman site to Heroku. To do this you’re going to need to have git installed, the Heroku toolbelt setup and a Heroku account (it’s free). We’re going to use the code from the Middleman-Heroku project template in this example. If you’re unfamiliar with git, check out this primer to get you started.

First of all, you’ll need to add a config.ru file to the root of your directory, with the code from here added in.

This file tells Heroku how to serve your website using Rack, from the build directory. It’s also worth adding a 404.html.erb page into your source directory just in case the server can’t find the file specified.

The next step is to add a Rakefile to the root of your directory that tells Heroku how to build your site.

namespace :assets do
task :precompile do
    sh "middleman build"
end
end

You’ll notice that this runs the middleman build command which will happen every time you deploy to Heroku.

Add your work to git:

$ git init
$ git add .
$ git commit -m "First commit of my site."

Next create a Heroku application. You can read more about this process on the Heroku help section.

$ heroku create

Once your application has been created you simply run

$ git push heroku master

This will deploy your site to Heroku, building the latest version of your site on the server. To verify it’s working just open up a web browser and visit the address (app-name.herokuapp.com) or run

$ heroku open   

Then every time you make a change, check it into git and run the git push heroku master command. Easy!

If you don’t fancy using Heroku, Middleman has a series of fantastic deployment plugins that you can use. Using rsync or git for deployment is also a really good option if you have your own server with ssh access. Whatever you do just don’t use FTP – it’s not 1999 anymore.

Wrapping up

Hopefully that’s given you a taste of developing websites in Middleman and made you want to switch your next project to be a static site. It’s certainly a good way to develop simple sites without relying on a big bulky framework or server-side technology whilst using great tools like Sass along the way.

We’ve used Middleman to build the Front-end London website, which is open sourced on Github if you’d like to see an example of a site built with Middleman please feel free to pull it down and take a look.

If you have any questions, or get stuck with anything here drop me a tweet and I’ll do my best to help.

Back to the articles