[005.1] Intro to Middleman

A look at Middleman, the Ruby based static HTML & CSS site builder

Subscribe now

Intro to Middleman [07.05.2017]

Today we are going to look at Middleman, a ruby based static site generator. Middleman will allow us to leverage modern development tools such as HAML and SASS to build static sites. Today we will setup a basic middleman project, explore its folder structure, then look at the build and publishing tools.

I've got a basic Ruby repository setup for our project, and it is open sourced as Rudiment. I'll be using it to cover some modern elements of front end web dev. Let's get started!

Installing Middleman

First off I'll install bundler and initialize middleman in my current folder with:

$ gem install bundler
$ gem install middleman
$ middleman init .

We can now start up middleman and confirm it's all working by running middleman. Note that this is shorthand for middleman server.

$ middleman

Now we can visit http://localhost:4567 to see that our server is running. Middleman provides a handy link to its documentation, which is wonderful. There are a lot of static site builders out there, and the reason I often come back to Middleman is both the quality of its documentation and third party plugin support -- but we'll get to those later.

Middleman also provides a configuration screen via localhost: http://localhost:4567/__middleman this allows you easy access to a browsable sitemap. This sitemap is really helpful because it allows you to see every file that Middleman is parsing, and what its output is.

For instance, if we open up the index.html tab we can see its source file is source/index.html.erb, its compiled path is index.html, and even that file specific data that is being sent up to the layout for use in the title. This level of verbosity is really useful when tracking down little bugs in your sites!

The configuration screen also allows us to browse the internal configuration of Middleman itself. We won't need this today, but will use it a lot more in the future.

Exploring Middleman's File Structure

Let's take a look at the files and folders that Middleman generated for us. In our top level we have a config.rb, that's the top level configuration for our project, and is where the internal configuration screen gets its properties from.

Next we have a Gemfile and corresponding Gemfile.lock. The lock file is automatically generated from the Gemfile when you run bundler. Our Gemfile lists Middleman and some platform specific dependencies. Together these files make our project easily portable, as we can just gem install bundler and bundle to have our project running on most any system with Ruby.

We have a handful of hidden files that have little impact on our html/css, but just make the project more portable and add to developer quality of life. These include ruby environment settings, a localized gemset, specified Ruby version, and git ignore rules.

Now on to the important stuff: the source folder. Inside of it we have places to keep images, javascript files, layouts and stylesheets. Any top level html file like the index.html.erb will be compiled into a page.

They aren't generated by default, but Middleman supports a few other directories here. You can make a lib directory to hold ruby files, and these function like helpers in Rails. You can also have a data folder with YAML or JSON files. These data files are parsed and made available as objects to your pages, so you independently change your data and how it is rendered. This is a big time saver.

Finally, when you build your site, you'll get a cleverly named build folder with the output.

Building static sites

Just by running middleman build we get a fully built and ready to publish version of our site. Let's try that now:

$ middleman build

Now our build folder exists and is populated with the initial site that Middleman ships with. We can see that the index content has been applied to the template and the title has been filled in properly from the data settings inside of the index page. We could easily drop the contents of our build folder onto S3, github, or any other static host to have our site live. There are a lot of Middleman packages to automate this for us, too!

ERB

Let's take a look at our layout.erb and index.html.erb page. Both of these are written in ERB, or Embedded Ruby templating syntax. It's just basic html with some Ruby hooks in it. The layout file is pretty simple.

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport"
          content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Use the title from a page's frontmatter if it has one -->
    <title><%= current_page.data.title || "Middleman" %></title>
    <%= stylesheet_link_tag "site" %>
    <%= javascript_include_tag "site" %>
  </head>
  <body>
    <%= yield %>
  </body>
</html>

In the title, we populate it with page data, or the string Middleman if that doesn't exist. There are a couple link tags to bring in the site stylesheet and javascript file. These call out to the configuration settings and lookup the default location for those file types and create a proper link or script tag as appropriate.

The line that tends to confuse people is the <%= yield %> call. Ruby encourages most functions to take a block. Calling yield just has the interpreter parse the contents of that passed block at that location. This means that our pages, like index.html.erb, are passed to the layout and placed inside of said layout when that yield is called. There isn't any magic here, we just dump the parsed contents of that file where yield goes.

The index.html.erb is even simpler.

---
title: Welcome to Middleman
---

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 340" class="middleman-logo" aria-labelledby="middleman-logo__title" role="img">
  <title id="middleman-logo__title">Middleman</title>
  <path class="middleman-logo__top-left-bar" fill-opacity=".45" d="M0 40L200 0v30L0 60z"/>
  <path class="middleman-logo__top-right-bar" fill="#fff" d="M200 0l200 40v20L200 30z"/>
  <path class="middleman-logo__left-m" fill-opacity=".45" d="M0 78v184l45 5V152l45 83 47-83v129l53 7V52l-57 8-43 83-43-70z"/>
  <path class="middleman-logo__right-m" fill="#fff" d="M400 78v184l-45 5V152l-45 83-47-83v129l-53 7V52l57 8 43 83 43-70z"/>
  <path class="middleman-logo__bottom-left-bar" fill-opacity=".45" d="M0 300l200 40v-30L0 280z"/>
  <path class="middleman-logo__bottom-right-bar" fill="#fff" d="M200 340l200-40v-20l-200 30z"/>
</svg>

<h1>
  Middleman is Running
</h1>

<%= link_to(
  "Read Documentation",
  "https://middlemanapp.com/basics/templating_language/",
  target: "_blank"
) %>

The first thing we see in this file is the data set up top for the title. This is optional and you aren't required to use data fields if you aren't comfortable with them. Next up is the content of our page, just an SVG and a heading. We end with a link_to call, which just generates a link. Again, if you'd prefer to just stick with html syntax you absolutely can, though if you've used Rails before then you'll be familiar with this function.

Creating our own site

Let's make some changes to their basic layout, and bring in the defaults we've worked up so far in the HTML & CSS topic. First we'll replace their layout with our basic page, and I'll go ahead and drop normalize, type base and a style css files into the stylesheets folder.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title><%= current_page.data.title || "Middleman" %></title>
    <%= stylesheet_link_tag "normalize" %>
    <%= stylesheet_link_tag "typebase" %>
    <%= stylesheet_link_tag "style" %>
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
    <%= yield %>
    <footer>
      <p>
        <%= current_page.data.footer || "Some random copyright" %>
      </p>
    </footer>
  </body>
</html>

We can also swap out the contents of our index.html.erb file with one we previously built:

---
title: Hello world, from Middleman
footer: There is some footer info here
---

<header>
  <h1>
    <%= current_page.data.title %>
  </h1>
</header>
<div class="content">
  <menu>
    <ul>
      <li><a href="#">Foo</a></li>
      <li><a href="#">Bar</a></li>
      <li><a href="#">Baz</a></li>
    </ul>
  </menu>
  <aside>
    <p>
      <!-- SNIP Lorem -->
    </p>
  </aside>
  <main>
    <p>
      <!-- SNIP Lorem -->
    </p>
    <p>
      <!-- SNIP Lorem -->
    </p>
    <p>
      <!-- SNIP Lorem -->
    </p>
  </main>
</div> <!-- content -->

I set two pieces of data up top. One for the header and one for the footer. These have both been rendered in the layout, as well the heading one in the h1 tag on the page. Setting data up top and using it inside of the page is a common pattern with Middleman, and is really convenient.

Finally let's rebuild our project:

$ middleman build

In looking at our index.html file we can see it all got updated properly, we built our first page with Middleman!

Summary

Today we looked at the basics of Middleman for building static sites. We explored how to install the framework and its basic file structure. We then saw how to build a site into static files, and looked briefly at ERB as a templating language. We then imported some previous pages we wrote into their basic setup, played with data, and rebuilt a static version of our page via Middleman.

Middleman is a great project, so we'll explore it more in the future as we start to look at SASS and HAML to make writing CSS and HTML more efficient. See you next time!

Resources