10 min read

Part 1: Getting up and running with Middleman

Many of today’s most prominent web frameworks, such as Ruby on Rails, Django, WordPress, Drupal, Express, and Spring MVC, rely on a server-side language to process HTTP requests, query data at runtime, and serve back dynamically constructed HTML. These platforms are great, yet developers of dynamic web applications often face complex performance challenges under heavy user traffic, independent of the underlying technology. High traffic, and frequent requests, may exploit processing-intensive code or network latency, in effect yielding a poor user experience or production outage.

Static site generators such as Middleman, Jeckyll, and Wintersmith offer developers an elegant, highly scalable alternative to complex, dynamic web applications. Such tools perform dynamic processing and HTML construction during build time rather than runtime. These tools produce a directory of static HTML, CSS, and JavaScript files that can be deployed directly to a web server such as Nginx or Apache. This architecture reduces complexity and encourages a sensible separation of concerns; if necessary, user-specific customization can be handled via client-side interaction with third-party satellite services.

In this three part series, we’ll walk-through how to get started in developing a Middleman site, some basics of Middleman blogging, how to migrate content from an existing WordPress blog, and how to deploy a Middleman blog to production. We will also learn how to create automated tests, continuous integration, and automated deployments.

In this part, we’ll cover the following:

  • Creating a basic Middleman project
  • Middleman configuration basics
  • A quick overview of the Middleman template system
  • Creating a basic Middleman blog

Why should you use middleman?

Middleman is a mature, full-featured static site generator. It supports a strong templating system, numerous Ruby-based HTML templating tools such as ERb and HAML, as well as a Sprockets-based asset pipeline used to manage CSS, JavaScript, and third-party client-side code. Middleman also integrates well with CoffeeScript, SASS, and Compass.


For this tutorial, I’m using an RVM-installed Ruby 2.1.2. I’m on Mac OSX 10.9.4.

Installing middleman

Install middleman via bundler:

$ gem install middleman

Create a basic middleman project called middleman-demo:

$ middleman init middleman-demo

This results in a middleman-demo directory with the following layout:

├── Gemfile
├── Gemfile.lock
├── config.rb
└── source
   ├── images
   │   ├── background.png
   │   └── middleman.png
   ├── index.html.erb
   ├── javascripts
   │   └── all.js
   ├── layouts
   │   └── layout.erb
   └── stylesheets
       ├── all.css
       └── normalize.css[SB4] 

There are 5 directories and 10 files.

A quick tour

Here are a few notes on the middleman-demo layout:

  • The Ruby Gemfile  cites Ruby gem dependencies; Gemfile.lock cites the full dependency chain, including  middleman-demo’s dependencies’ dependencies
  • The config.rb  houses middleman-demo’s configuration
  • The source directory houses middleman-demo ’s source code–the templates, style sheets, images, JavaScript, and other source files required by the  middleman-demo [SB7] site

While a Middleman production build is simply a directory of static HTML, CSS, JavaScript, and image files, Middleman sites can be run via a simple web server in development.

Run the middleman-demo development server:

$ middleman

Now, the middleman-demo site can be viewed in your web browser at  http://localhost:4567.

Set up live-reloading

Middleman comes with the middleman-livereload gem. The gem detects source code changes and automatically reloads the Middleman app.

Activate middleman-livereload  by uncommenting the following code in config.rb:

# Reload the browser automatically whenever files change
configure :development do
 activate :livereload

Restart the middleman server to allow the configuration change to take effect. Now, middleman-demo should automatically reload on change to config.rb and your web browser should automatically refresh when you edit the source/* code.

Customize the site’s appearance

Middleman offers a mature HTML templating system. The source/layouts directory contains layouts, the common HTML surrounding individual pages and shared across your site. middleman-demo uses ERb as its template language, though Middleman supports other options such as HAML and Slim.

Also note that Middleman supports the ability embed metadata within templates via frontmatter. Frontmatter allows page-specific variables to be embedded via YAML or JSON. These variables are available in a current_page.data namespace. For example, source/index.html.erb contains the following frontmatter specifying a title; it’s available to ERb templates as current_page.data.title:

title: Welcome to Middleman

Currently, middleman-demo is a default Middleman installation. Let’s customize things a bit.

First, remove all the contents of source/stylesheets/all.css  to remove the default Middleman styles.

Next, edit source/index.html.erb to be the following:

title: Welcome to Middleman Demo

<h1>Middleman Demo</h1>

When viewing middleman-demo at http://localhost:4567, you’ll now see a largely unstyled HTML document with a single Middleman Demo heading.

Install the middleman-blog plugin

The middleman-blog plugin offers blog functionality to middleman applications. We’ll use middleman-blog in middleman-demo.

Add the middleman-blog version 3.5.3 gem dependency to middleman-demo by adding the following to the Gemfile:

gem "middleman-blog", "3.5.3

Re-install the middleman-demo gem dependencies, which now include middleman-blog:

$ bundle install

Activate middleman-blog and specify a URL pattern at which to serve blog posts by adding the following to config.rb:

activate :blog do |blog|
  blog.prefix = "blog"
  blog.permalink = "{year}/{month}/{day}/{title}.html"

Write a quick blog post

Now that all has been configured, let’s write a quick blog post to confirm that middleman-blog works.

First, create a directory to house the blog posts:

$ mkdir source/blog

The source/blog directory will house markdown files containing blog post content and any necessary metadata. These markdown files highlight a key feature of middleman: rather than query a relational database within which content is stored, a middleman application typically reads data from flat files, simple text files–usually markdown–stored within the site’s source code repository.

Create a markdown file for middleman-demo ’s first post:

$ touch source/blog/2014-08-20-new-blog.markdown

Next, add the required frontmatter and content to source/blog/2014-08-20-new-blog.markdown:

title: New Blog
date: 2014/08/20
tags: middleman, blog

Hello world from Middleman!


  • Rich templating system
  • Built-in helpers
  • Easy configuration
  • Asset pipeline
  • Lots more 

Note that the content is authored in markdown, a plain text syntax, which is evaluated by Middleman as HTML. You can also embed HTML directly in the markdown post files. GitHub’s documentation provides a good overview of markdown.

Next, add the following ERb template code to source/index.html.erb [SB37] to display a list of blog posts on middleman-demo ’s home page:

 <% blog.articles.each do |article| %>
     <%= link_to article.title, article.path %>
 <% end %>

Now, when running middleman-demo and visiting http://localhost:4567, a link to the new blog post is listed on middleman-demo ’s home page. Clicking the link renders the permalink for the New Blog blog post at blog/2014-08-20/new-blog.html, as is specified in the blog configuration in config.rb.

A few notes on the template code

Note the use of a link_to method. This is a built-in middleman template helper. Middleman provides template helpers to simplify many common template tasks, such as rendering an anchor tag. In this case, we pass the link_to method two arguments, the intended anchor tag text and the intended href value. In turn, link_to generates the necessary HTML.

Also note the use of a blog variable, within which an article’s method houses an array of all blog posts. Where did this come from?  middleman-demo is an instance of  Middleman::Application;  a blog  method on this instance.

To explore other Middleman::Application methods, open middleman-demo via the built-in Middleman console by entering the following in your terminal:

$ middleman console

To view all the methods on the blog, including the aforementioned articles method, enter the following within the console:

2.1.2 :001 > blog.methods

To view all the additional methods, beyond the blog, available to the Middleman::Application instance, enter the following within the console:

2.1.2 :001 > self.methods

More can be read about all these methods on Middleman::Application’s rdoc.info class documentation.

Cleaner URLs

Note that the current new blog URL ends in .html. Let’s customize middleman-demo to omit .html from URLs. Add the following config.rb:

activate :directory_indexes

Now, rather than generating files such as /blog/2014-08-20/new-blog.html,  middleman-demo generates files such as /blog/2014-08-20/new-blog/index.html, thus enabling the page to be served by most web servers at a /blog/2014-08-20/new-blog/ path.

Adjusting the templates

Let’s adjust our the middleman-demo ERb templates a bit.

First, note that <h1>Middleman Demo</h1> only displays on the home page; let’s make it render on all of the site’s pages. Move <h1>Middleman Demo</h1> from  source/index.html.erb  to source/layouts/layout.erb. Put it just inside the <body> tag:

<body class="<%= page_classes %>">
   <h1>Middleman Demo</h1>
   <%= yield %>

Next, let’s create a custom blog post template.

Create the template file:

$ touch source/layout/post.erb

Add the following to extend the site-wide functionality of source/layouts/layout.erb to  source/layouts/post.erb:

<% wrap_layout :layout do %>
 <h2><%= current_article.title %></h2>
 <p>Posted <%= current_article.date.strftime('%B %e, %Y') %></p>
 <%= yield %>
 <% current_article.tags.each do |tag| %>
   <li><a href="/blog/tags/<%= tag %>/"><%= tag %></a></li>
 <% end %>
<% end %>

Note the use of the wrap_layout  ERb helper.  The wrap_layout ERb helper takes two arguments. The first is the name of the layout to wrap, in this case :layout. The second argument is a Ruby block; the contents of the block are evaluated within the <%= yield %> call of source/layouts/layout.erb.

Next, instruct  middleman-demo  to use  source/layouts/post.erb  in serving blog posts by adding the necessary configuration to  config.rb :

page "blog/*", :layout => :post

Now, when restarting the Middleman server and visiting  http://localhost:4567/blog/2014/08/20/new-blog/,  middleman-demo renders a more comprehensive blog template that includes the post’s title, date published, and tags.

Let’s add a simple template to render a tags page that lists relevant tagged content.

First, create the template:

$ touch source/tag.html.erb

And add the necessary ERb to list the relevant posts assigned a given tag:

<h2>Posts tagged <%= tagname %></h2>
 <% page_articles.each do |post| %>
   <a href="<%= post.url %>"><%= post.title %></a>
 <% end %>

Specify the blog’s tag template by editing the blog configuration in config.rb:

activate :blog do |blog|
 blog.prefix = 'blog'
 blog.permalink = "{year}/{month}/{day}/{title}.html"
 # tag template:
 blog.tag_template = "tag.html"

Edit config.rb to configure middleman-demo’s tag template to use source/layout.erb rather than source/post.erb:

page "blog/tags/*", :layout => :layout

Now, when visiting http://localhost:4567/2014/08/20/new-blog/, you should see a linked list of New Blog’s tags. Clicking a tag should correctly render the tags page.

Part 1 recap

Thus far, middleman-demo serves as a basic Middleman-based blog example. It demonstrates Middleman templating, how to set up the middleman-blog  plugin, and how to make author markdown-based blog posts in Middleman.

In part 2, we’ll cover migrating content from an existing WordPress blog. We’ll also step through establishing an Amazon S3 bucket, building middleman-demo, and deploying to production.

In part 3, we’ll cover how to create automated tests, continuous integration, and automated deployments.

About this author

Mike Ball is a Philadelphia-based software developer specializing in Ruby on Rails and JavaScript. He works for Comcast Interactive Media where he helps build web-based TV and video consumption applications.


Please enter your comment!
Please enter your name here