Advertisement
  1. Web Design
  2. UX/UI
  3. Prototyping

How to Set Up a Static Website With Middleman

Scroll to top
Read Time: 17 min
This post is part of a series called Building Static Websites with Middleman.
Working With Data, Assets, and Templates in Middleman

This is part one of a small series about Middleman, “a static site generator using all the shortcuts and tools in modern web development”. The first two tutorials will cover the basics, after which we’ll put what we’ve learned into action with a practical project. Middleman does require the use of Ruby, but don’t hesitate to read on if this is alien to you; this series is completely newbie-friendly.

Middleman and Static Pages

What’s all the fuzz lately with static sites? Well, they’re fast, pretty straightforward to set up and lightweight. As you’re not serving anything database related, static sites are pretty reliable and speedy. HTML, CSS and if needed JS—that’s all.

Many people use static websites to set up their blogs and personal pages. Landing pages that are hit by traffic heavily are also a good candidate. HealthCare.gov from the Obama administration famously used Jekyll, another static site generator, for their site. If you need something quick and easy, which is able to scale out of the box, static sites can be amazing. Especially as you can host them for free on GitHub Pages or Heroku.

filefilefile

Arguably the whole static site hipness started a few years back when Jekyll came along. Of course, static sites are as old as the first “Hello World!” from Sir Tim Berners-Lee but over the past 15 years, database backed apps became “all that mattered”. A couple of years back, one of the co-founders of GitHub needed a better way to write blogs and he came up with Jekyll—this hip static site generator for “Blogging like a hacker”. I’ve used it on a couple of occasions and have only good things to report. The core team is awesome too. Anyhow, for this series my editor and I agreed it would be more interesting to cover Middleman. It might be fair to say that Middleman is a bit less “blog-aware” out of the box, but nonetheless equally as powerful and great quality-wise.

filefilefile

Ruby

Middleman uses Ruby, offering a pretty extensive set of features to build cool stuff. If you’ve ever used Rails or Sinatra you’ll feel right at home. It seems Middleman and Jekyll are the go-to options for static sites in the Ruby community. I have also heard more and more designers argue that they like using them for prototyping and for setting up their own personal pages. What a lot of these static site frameworks have in common is that they are pretty straightforward to use.

In this article I’ll assume that you are at least a bit interested in Ruby, and have it installed on your system. If you need help, take a look at Ruby for Newbies: Installing Ruby and Getting Started by Andrew Burgess.

Knowing how to deal with RubyGems is necessary too, and, again, Andrew Burgess’ Ruby for Newbies: Working with Gems will help you get started if needed. I’ll do my best not to go over your head with programming concepts, but I won’t be covering programming basics like loops, code blocks and such. For the newbies among you, don’t worry, Middleman doesn’t have that many moving parts, and I’ll demonstrate how easy it is to learn.

Installation and Getting Started

So you have Ruby and RubyGems under your belt? Great, then we’re good to go.

Open up your terminal and enter:

1
2
gem install middleman

If you are denied permission to do so, you’ll need to prepend the command with sudo and enter your system admin password. After this process has finished, you’ll be able to use a couple of handy middleman commands via the command prompt.

filefilefile

middleman init

This command initiates a new project. You’ll need to provide it with the name of your app, then hit enter.

1
2
middleman init your_fancy_app

It also takes additional arguments like which template you want start with. This makes it really handy to customize your apps with templates right from the start, cutting down on repetitive setup tasks quite a bit! We’ll discuss more on templates in a later tutorial.

1
 
2
middleman init your_fancy_blog --template=blog
1
2
middleman init your_fancy_mobile_app --template=mobile

middleman server

Middleman comes with a local server for your development. Starting it up lets you see your site at https://localhost:4567/ **. If you just enter **middleman without any additional argument, this will also fire your server up. Shut down your server with CTRL-c.

middleman build

Once you have something you are ready to put on an internet-facing server you need to build your site. This means that whatever you have prepared in your /source folder will be processed and the final output will be output to the /build folder which middleman also creates for you. All your files which use preprocessors like Slim, Haml, Sass, CoffeeScript will be processed into their respective counterparts and put into your /build directory.

middleman deploy

Once your site is ready to face the internet, this command deploys your /build folder onto your web server. Every update you make will go through this process.

livereload

Do yourself a favor right away and activate LiveReload to automatically refresh your pages after changes to your HTML, Sass or JS files. This is of great convenience during development—you won’t regret it! Middleman these days offers LiveReload out of the box—you just need to add

1
2
gem 'middleman-livereload'

to your Gemfile and uncomment the following line in config.rb:

1
2
# Reload the browser automatically whenever files change
3
activate :livereload

Then you bundle Middleman

1
2
bundle
3
#or
4
bundle exec middleman

Source vs. Build vs. Deploy

So let’s get get started with /source and /build folders. Between them is the dividing line that separates your development and production sections. When you use your local web server for development, /source gets used to serve your app. The /build folder is used by your non-local servers to serve your static pages. /build gets created every time you use middleman build in your command line. Therefore, you should be careful not to accidentally spend your time coding in /build because this work will disappear after the build process. In general, all your development is supposed to happen in /source.

The build process creates the static sites that you want your server to host. Each file in your /source folder will get processed and then stored in /build. As mentioned before, your Sass, CoffeeScript, Slim / Haml and partials will process into their deplyable counterparts. All the layouts will be pieced together as well. If you have activated compression for these files, this is the moment they get “uglified” too. During this whole shabang, the /build folder gets rejuvinated by getting rid of files that have no reference in /source anymore. During middleman build, any changes you’ve made to files in /source will trigger a regeneration of new corresponding static files for /build.

The deployment process is the last step. With the /build directory in place you have everything you need to put your app out there. My recommendation is to do this early to avoid running into any surprises.

A New Site

Let’s check out the basic structure of a Middleman app. The main components are:

  • /images
  • /javascripts
  • /layouts
  • /stylesheets
  • config.rb
  • An index.html.erb file
  • A Gemfile

As you can see below, the most Jazz goes into the /source folder. What I like about Middleman apps is their simple organization. Navigating the document structure is straight forward, even for beginners.

filefilefile

If you are unhappy with the naming of some of these folders you can change that in your configurations (config.rb). The same names will be used for your finished /build folder.

1
2
set :css_dir,    'custom_folder_name'
3
4
set :js_dir,     'custom_folder_name'
5
6
set :images_dir, 'custom_folder_name'

Once you have your server running, you can check out other options to configure Middleman right in your browser: http://localhost:4567/__middleman/config/. Not all of them might make sense, or are even important to know at this stage. Give it a glance and a mental bookmark is totally sufficient for now.

One you run middleman build you can peek into the /build folder. All the plain HTML, CSS and JS files you need to serve your static site.

filefilefile

That’s pretty much all you need to know to get started and to orient yourself.

Suggestion: At this pont it would make a lot of sense if you start putting together a test app yourself. Look around and get a feel how things are organized and how the pieces fit together.

Front Matter

The term Front Matter comes from book publishing, and it refers to the information at the front of a book. In the case of static website files, it refers to blocks of information which are stored in YAML. Every page allows you to have variables that can be stored right at the top inside a leading and a trailing triple hyphen. For example, here’s the top of a fictional file called: some.html.erb.

1
2
---
3
4
layout: Bond
5
title:  Favorite bond girl names
6
date:   2015-11-09
7
tags:   bond, 007
8
9
some_secret: I won’t get rendered until you use me.
10
11
bond_girls:
12
  - Strawberry Fields 
13
  - Jill Masterson
14
  - Tiffany Case
15
16
---
17
18
Top three names for Bond girls
19
20
<ul>
21
  
22
    <li>
23
  
24
</ul>
25

The YAML variables look just like a hash. You can access that local data through the current_page object:

1
2
current_page.data.some_variable

You often use this to store tags, dates, titles and configuration options—like which layout you want to use for particular pages. Front matter is a YAML store for your variables. You can also use JSON if you prefer that. Think of it as a place for putting data that could normally reside in a database. I will discuss the various options and uses along the way when they come up.

ERB

This is a good opportunity to briefly go over ERB. ERB lets you create dynamic templates which have embedded code in them. Your filenames need to have an .erb extension and you need to put your code in the following two “containers”.

For code that gets exectuted but not “printed” onto the page you use this:

1
2

Think of it as “computation only”.

Otherwise, for return values that you want to see show up “printed” on the page, you need to add an equals sign as well. That’s it.

1
2

Layouts

The concepts of layouts and partials are closely related. Let me give you a little whirlwind tour in case you haven’t played with Rails, Sinatra or similar before. I think I should start with layouts first.

Layouts provide you with the structure to share common markup among different pages—that belong to the same “family” of pages. It’s a tool to avoid duplication and to speed up your work. Instead of writing the same HTML skeleton all over the place you compose layouts for particular use cases. Popular examples are two different layouts for both an admin and a “normal” user. They usually have a very different experience looking at the “same” page.

When you initiate a simple middleman app, you’ll automatically get a layout.erb file in source/layouts. Take note that this file ends in .erb and not .html.erb. Layouts should not be rendered to HTML and Middleman will throw an error if you create layouts with an .html extension. If you use a different templating language like Slim or Haml, layouts could have their extensions instead. As the default suggests, you should put all your layouts into the /layouts folder in source.

Here’s an example of source/layouts/layout.erb:

1
2
3
4
  
5
    
6
7
    
8
    
9
10
    
11
    
12
13
    
14
    
15
  
16
17
  
18
    
19
  
20

This default layout is pretty barebones, but provides all you need to get started. Let’s have a look:

  • A little bit of meta information.
  • A dynamic page title that reads data from every pages’ front matter.
  • Helper methods that include style and JavaScript files.
  • And finally a body tag to wrap your content which is “yielded” into the layout via **.

And from there you can customize this layout to your every need. One potentially confusing aspect for Ruby newbies is the yield keyword—this just means that it passes through the rest of the content you create. In other words, yield is a placeholder for your views which will get rendered into it. If that concept is completely alien to you just remember to not touch it for now or your app might not work as expected. Whenever you create your own layouts, having yield in there is essential, otherwise your content won’t show. You’ll get the hang of it in no time, I promise.

If you created different layouts, you can specify via the front matter which layout you want to use on a page-by-page basis. Let’s say you have a special layout for welcoming users that is a bit more salesy. Here we have welcome.html.erb.

1
2
---
3
layout: sales
4
---
5
6
Hello there!
7
 Guess what, we’re trying to sell you some stuff?

Alternatively you can specify layouts in your config.rb file.

1
2
page "/welcome.html", :layout => "sales"

If you want to avoid doing this for every page manually, you can collect them in one place. Again, in config.rb, you use a wildcard (**\***) to collect a bunch of pages that use the same layout.

1
2
page "/sales/*", :layout => "sales"

I personally like to put this layout info in the front matter. It’s very explicit and not too repetetive. If I had a whole bunch of them, however, I’d rather use the wildcard approach.

Partials

Partials provide you with the means to encapsulate view code that you can reuse wherever you need. You just need to tell your view where to insert a partial and it gets rendered right in there. Partials are a very common technique for DRYing up your code.

Very common examples include navbars, footers and head sections, which you wouldn’t want to duplicate all over the place. Files for partials start with an underscore. For starters you can place them under /source. Your layouts are a good place to start with collecting code to extract into partials. Whenever you find something you need to reuse, partials will be a handy friend.

Here’s an example of /source/layouts/layout.erb.

1
2
3
4
  
5
    
6
  
7
8
  
9
    
10
    
11
    
12
  
13

And the partial source/_head.html.erb:

1
2
3
4
5
6
7
8
9
10
11

Sometimes you’ll want to extract a partial not just for avoiding duplication but to make your views more readable. Over time, head sections are notorious for becoming quite loaded, for example. Within them you can have other partials that only deal with style or JS files.

You’ll realize how convenient partials are once you can apply changes that ripple through your entire app—wherever you included the partial. There’s no need to go through a bunch of files to apply the same change over and over.

Helpers

Helpers are methods that you can use for a lot of everyday tasks in your views. I believe this was pioneered in Rails land and quickly became ubiquitous for web modern web development. You’ve already seen helpers that include stylesheets and JavaScript files. There’s a lot more where this is coming from though.

Here’s our /source/_head.html.erb partial again:

1
2
3
  
4
  
5

These helpers are meant to help you write cleaner and more concise view code. In the helpers list below you’ll find a lot of useful stuff that comes out of the box. You are not limited by these though. Write your own helper methods in config.rb or collect them separately in a module.

It works like this: In your config.rb you create a helpers block and put all your helper methods inside. That’s it. Now your views have access to them.

Example: /source/_navbar.erb.

1
2
3
  
4
  
5
6

And in config.rb:

1
2
helpers do
3
4
  def random_username
5
    "#{lorem.first_name} #{lorem.last_name}"
6
  end
7
8
  def random_image
9
    image_tag "#{lorem.image('30x40', :background_color => '333', :color => 'fff')}"
10
  end
11
12
end

These helpers might come in handy when I quickly want to prototype something and want to avoid setting up dummy images and text myself. Overall, you should look out for code that you’d like to be more concise or that you duplicate over and over again. Helpers are often a good home for that.

Inside these custom helpers I used other Middleman helpers for creating img tags through image_tag as well as the lorem object for some random user names and image placeholders. These lorem thingies can be a bit customized to suit your needs.

Using the module approach however, you need a separate file for your module. Create a “lib” directory in your root folder (the same level as “source” and “build”) and create a file for your helpers.

Here we have /lib/helpers.rb:

1
2
module PrototypingHelpers
3
  def random_image
4
    image_tag "#{lorem.image('300x400', :background_color => '333', :color => 'fff')}"
5
  end
6
7
  def random_username
8
    "#{lorem.first_name} #{lorem.last_name}"
9
  end
10
end

Then you’ll need to let your config.rb file know that you want to use these helpers:

1
2
require 'lib/helpers'
3
helpers PrototypingHelpers

Boom! You’re ready to roll. In general, I’d go with the module approach right away. It feels a lot cleaner to me, plus you avoid polluting your config file with too much stuff.

I’d also like to look into output helpers and content_for in particular, since they can be a bit confusing for newbies. This lets you capture a bunch of content that you can yield / reuse someplace else. It’s a minature partial of sorts. I would personally go with a partial most of the time, but every now and then when you want to apply on-off changes more surgically this is handy to know:

Here’s index.html.erb:

1
2
3
  
4
<ul>
5
    <li>
6
    <li>
7
    <li>
8
    <li>
9
  </ul>
10
11
12
 Hello new user!
13
...

And admin_index.html.erb:

1
2
3
  
4
<ul>
5
    <li>
6
    <li>
7
    <li>
8
    <li>
9
    <li>
10
    <li>
11
  </ul>
12
13
14
15
  
16
  
17
18
19
 Hello Ms. Admin!
20
...

Then in layout.erb:

1
2
    
3
    

content_for?

The key is using yield_content which is putting your collected content from the individual page into the layout—if found. There’s no need to just use them only with layouts either. When you need to make this a bit more involved, use content_for? to check for specific content blocks before you insert them. It is handy when you want to make small adaptions for sections that differ only slightly. It’s great that you can save this content a bit like a configuration on the relevant pages themselves and “activate” it only where needed. You probably shouldn’t get too clever with these things though.

link_to

A word about the link_to helper I used above. This is probaly the one you’ll run into most often. You essentially feed the method a name and a url or path where this link should point to. I replaced the last part with a placeholder for brevity.

Below is an overview of which helpers are out-of-the-box at your disposal. I think the names are mostly self-explanatory and I shouldn’t go over what each of these can help you with. Make a mental bookmark of what’s out there and check back with the documentation if they give you any trouble.

Tag Helpers

  • tag
  • link_to
  • input_tag
  • favicon_tag
  • stylesheet_link_tag
  • javascript_include_tag

Output Helpers

  • content_for
  • content_for?
  • capture_html
  • yield_content
  • concat_content

Form Helpers

  • form_tag
  • label_tag
  • select_tag
  • submit_tag
  • field_set_tag
  • text_field_tag
  • check_box_tag
  • password_field_tag

Format Helpers

  • truncate
  • pluralize
  • word_wrap
  • escape_html
  • simple_format
  • js_escape_html
  • time_ago_in_words
  • distance_of_time_in_words

Lorem Helpers

  • lorem.date
  • lorem.word
  • lorem.name
  • lorem.email
  • lorem.image
  • lorem.words
  • lorem.sentence
  • lorem.last_name
  • lorem.paragraph
  • lorem.first_name
  • lorem.paragraphs

Final Thoughts

I believe this is a good basis to start playing around with a toy app. You should have a good sense of what Middleman offers and how to navigate the framework. In the next part of this series we’ll take things further and dive a bit deeper into the framework. The Middleman team has really done a great job with designing the API and with keeping things simple.

Hopefully you can see by now why this framework has gained in popularity and why it is a good choice for all sorts of static projects.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.