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.