Static Sites with Middleman

We’ve recently really taken a liking to building and deploying static sites using middleman. Middleman is a ruby gem that uses a tool chain familiar to rails developers, and simple enough to grasp for those less familiar with rails, and even ruby.

Before we dig into middleman, here’s a little wishlist of an ideal static site development tool:

  • Dynamic code reloading in development via livereload or browsersync.
  • Blogging built-in.
  • Easily utilize latest development tools such as SCSS / Compass, Less, Coffeescript, etc.
  • Templating language / layouts to reduce code duplication.
  • Entire site can be compiled to static html in a single command.
  • Rails-style approach to production assets. This means we need to be able to use a CDN to serve hashed assets. The ability to use hashed asset URLs is important in production so we can set far in the future cache headers and serve those assets through a CDN like Cloudfront, Akamai, Cloudflare, et al.
  • Can be deployed on a normal web server without a backend. Preferably on Amazon S3 or something similar with Cloudfront serving assets.

Middleman to the Rescue

Middleman enables a very familiar and productive workflow: a rich toolchain during development, but with the ability to compile the site down to static HTML and deploy to a simple webserver like Amazon S3.

Development with Browsersync

Middleman comes with built-in support for livereload, but I prefer browsersync (Node.js), as it’s a bit more responsive to file changes due to it’s architecture. Using it with middleman is painless:

1
2
3
npm install -g browser-sync
middleman server
browser-sync start --proxy 'localhost:4567' --files source

By default, middleman server launches a ruby dev server on port 4567. Browsersync has a handy --proxy mode that sits in front of another server and proxies requests to it. When browsersync starts up, it’ll look for the first available port starting with 3000 and it’ll open a new chrome tab on localhost:3000 instead of 4567.

Now, any changes you make will trigger an automatic page reload.

To make things a little easier, we like to stick these two commands in a Procfile and run our development environment using foreman.

1
2
browsersync: browser-sync start --proxy 'localhost:4567' --files source
server: middleman server

Blogging

Middleman comes with a built-in blogging extension.

Add it to your Gemfile:

1
gem 'middleman-blogging'

Activate it in the middleman config.rb file:

1
activate :blog

Generate a new post with the middleman helper:

1
middleman article "Article Title"

Read more about the middleman blogging extension here.

Compiling to Static HTML

Middleman comes with a handy middleman build command which takes your existing site and compiles everything to static HTML. The build command writes your entire site to the build directory, making it easy to ship to a deployment server.

Deployment to Amazon S3 and Cloudfront

Deploying the site to S3 is super simple thanks to the middleman-s3_sync extension. Add it to your Gemfile, and configure it in your config.rb file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
activate :s3_sync do |s3_sync|
  s3_sync.bucket                     = 'yourdomain.com' # The name of the S3 bucket you are targetting. This is globally unique.
  s3_sync.region                     = 'us-east-1'     # The AWS region for your bucket.
  s3_sync.aws_access_key_id          = 'ACCESS_KEY'
  s3_sync.aws_secret_access_key      = 'SECRET_ACCESS_KEY'
  s3_sync.delete                     = false # We delete stray files by default.
  s3_sync.after_build                = true # We do not chain after the build step by default.
  s3_sync.prefer_gzip                = true
  s3_sync.path_style                 = true
  s3_sync.reduced_redundancy_storage = false
  s3_sync.acl                        = 'public-read'
  s3_sync.encryption                 = false
  s3_sync.prefix                     = ''
  s3_sync.version_bucket             = false
end

The S3 sync extension also supports loading your credentials from a .s3_sync file located in the project root directory. You should use this to keep your Amazon credentials out of source control.

There are two ways to ship your build directory to S3. You can enable the after_build setting in your s3sync config, which will automatically deploy your site to your S3 bucket after running middleman build, or, you can run `middleman s3sync` manually.

Check out this page from AWS for more info on hosting a static site on S3.

More Resources

ruby web middleman aws