Given you’re a professional website designer and would like to work on some wonderful project. This project might be about designing a new website with a blog and a shop for one of your favourite customers. To get involved in this project, she asked you to design a mock-up with your ideas first and send it to her. In this article I’m going to show you how you can give away your mock-up in an easy manner without setting up a full-blown web server stack.


Short introduction to “middleman”

I really like middleman to build websites. In this article I’m going to use it, to create the mock-up. middleman is a static site generator written in Ruby and it supports a wide variety of template languages such as ERuby, Haml, Markdown or Liquid – see the this README for a full list of supported template languages. If you would like to use any of those template languages, make sure that you’ve got the required gems installed, e.g. erubis for Eruby and/or haml for Haml.

I even use middleman for some more exotic use cases like building proxy.pac-files – see this article for an introduction to proxy.pac-files – or to generate error pages for proxy servers. It’s also a great tool to serve HTML-presentations build ontop of reveal.js.

While developing a site I use the preview-server a lot. To push a new version of a site I’m responsible for, I build and upload it with capistrano-middleman.

Workflow to give away mock-up

Given that your customer has chosen you as contractor and you’ve finished the first iteration of the mock-up. To share this version of the site you and your customer need to perform the following steps shown in Fig 1. – at least in the context of this article.

Share local files

Fig. 1: Give away your mock-up to your customer

Getting started

Install “middleman”

To install middleman you need to use Rubygems. I’m going to use the latest version available of the v3-branch, v3.4.0.

gem install middleman -v 3.4.0
# => Successfully installed middleman-3.4.0
# => 1 gem installed

Create “middleman”-site

After installing middleman you setup a simple site first by using the init-command. This site is our mock-up for the time being.

middleman init new_site
# => create  new_site/Gemfile
# =>   run  bundle install from "."
# => Using i18n 0.7.0
# [...]
# => Using middleman 3.4.0
# => Bundle complete! 1 Gemfile dependency, 44 gems now installed.
# => Use `bundle show [gemname]` to see where a bundled gem is installed.
# =>   create  new_site/.gitignore
# =>   create  new_site/config.rb
# =>   create  new_site/source/index.html.erb
# =>   create  new_site/source/layouts/layout.erb
# =>   create  new_site/source/stylesheets
# =>   create  new_site/source/stylesheets/all.css
# =>   create  new_site/source/stylesheets/normalize.css
# =>   create  new_site/source/javascripts
# =>   create  new_site/source/javascripts/all.js
# =>   create  new_site/source/images
# =>   create  new_site/source/images/background.png
# =>   create  new_site/source/images/middleman.png

When the generator has finished, please switch to the newly created directory.

cd new_site

Start “middleman”-server

Before you start working on your mock-up, run middleman’s preview server. This server serves your site locally and instantly shows all changes made to the site if you enabled the LiveReload-extension.

    • Pro-Tip
  • Use tmux and spawn a new shell where you run the server. tmux is a terminal multiplexer similar to screen.
bundle exec middleman server -p 44184
# => == The Middleman is loading
# => == View your site at "http://localhost.localdomain:44184", ""
# => == Inspect your site configuration at "http://localhost.localdomain:44184/__middleman", ""

Work on mock-up

Now you can work on your mock-up and see the changes at once, if open the following URL http://localhost:44184 in your browser.

Build mock-up

Besides the preview server, it contains a command to build the static version of your site. With this command you create HyperText Markup Lanuage (HTML)-files from your templates aka views. Please run this command in another terminal.

bundle exec middleman build
# [...]
# => create  build/stylesheets/all.css
# => create  build/stylesheets/normalize.css
# [...]

Download web server

To make it easier to give away a presentation built with middleman-presentation, I developed a statically compiled web server in Go. Since this server is available for Linux, Windows and Mac OS X, I’m going to use this one for this article as well. Before you download the binary suitable for your own system, make sure, that you built the middleman-site. To check if you got the correct executables use the checksums found in this file.

# Download binary for Mac OS X
curl -L -o build/server.darwin.amd64

# Download binary for Linux 64-bit
curl -L -o build/server.linux.amd64

# Download binary for Windows 64-bit
curl -L -o build/

Alternatively and if it’s no problem for you to have binaries in your version control system’s (VCS) repository, download the server-binaries and add them to middleman’s source-directory. If you build the site with this kind of setup, middleman will copy the server files on every build to the build/-directory. Doing it this way makes it easier if you have very short iterations and sent your customer new mock-ups very regularly.

# Download binary for Mac OS X
curl -L -o source/server.darwin.amd64

# Download binary for Linux 64-bit
curl -L -o source/server.linux.amd64

# Download binary for Windows 64-bit
curl -L -o source/

Before running any of the executable files or give them away, please verify the checksum of each downloaded file. All checksums can be found online.

echo "21d791b1fa4de77d5c92f34f7d17aa6b40bee455d11a171d6a23e28aa2e76f7b  source/server.linux.amd64" | sha256sum -c
# => source/server.linux.amd64: OK
echo "87adbbcfb28f8996d3e71c734c5e00132d478c96587dbe097e4f2586c0caf027  source/server.darwin.amd64" | sha256sum -c
# => source/server.darwin.amd64: OK
echo "64e515f0f92f3a3e2d138402c77aa6c68c36cefeb8b59d074516afd288a5003d  source/" | sha256sum -c
# => source/ OK

echo "21d791b1fa4de77d5c92f34f7d17aa6b40bee455d11a171d6a23e28aa2e76f7b  build/server.linux.amd64" | sha256sum -c
# => build/server.linux.amd64: OK
echo "87adbbcfb28f8996d3e71c734c5e00132d478c96587dbe097e4f2586c0caf027  build/server.darwin.amd64" | sha256sum -c
# => build/server.darwin.amd64: OK
echo "64e515f0f92f3a3e2d138402c77aa6c68c36cefeb8b59d074516afd288a5003d  build/" | sha256sum -c
# => build/ OK

You then need to set the executable bit for the binaries. Please make sure, that you set the bit before adding the files to the VCS’ repository.

# Set executable bit for servers in "build"-directory
chmod +x build/server*

# Set executable bit for servers in "source"-directory
chmod +x source/server*

If you decided to add the server files to the source-directory of your local repository, please run the build-command again.

# Build the site again
bundle exec middleman build

Create an archive

After that, you need to create a package you can share with your customer. Please make sure, that you choose an archive-creator your customer uses as well. I prefer to use tar to create archives together with gzip – even graphical archive programs for Windows support the used algorithms.

# Create tar.gz archive
tar --xform 's/^\./2015-10-08-my-customer-her-site/' -cf 2015-10-08-my-customer-her-site.tar.gz -C build .

# Check content
tar -tf 2015-10-08-my-customer-her-site.tar.gz

An alternative would be to use zip.

# Rename directory
mv build 2015-10-08-my-customer-her-site

# Create archive
zip -r 2015-10-08-my-customer-her-site

# Check content
unzip -l 

Give away your mock-up

If you’re done with that, you can send your customer the package with the mock-up. She needs to extract the contents with one of the commands given below or use some graphical utility, and run the server.

# Extract archive
tar -xzf 2015-10-08-my-customer-her-site.tar.gz

# Alternative: Extract archive

# Switch to archive
cd 2015-10-08-my-customer-her-site

# Run server

The server will ask her for a network interface it should listen on. If she does not know anything about networking, she only needs to wait a few seconds and the server will choose to listen on localhost and opens the web site in her favourite web browser.

Wrap specific commands with “rake”

You may want to use rake – Ruby’s kind of make – to wrap project-specific commands. Personally I find it easier to remember to run rake build to build a site, than to run command_x; command_y; command_z – especially if you work on multiple very different projects in parallel. You can use this very simple Rakefile for your own project. Please don’t forget to add gem rake to your projects’s Gemfile and install the gem via bundle install.

customer_name  = 'my-customer'
site_name      = 'her-site'
date           ='%Y-%m-%d')
directory_name = "#{date}-#{customer_name}-#{site_name}"
file_name      = "#{directory_name}.tar.gz"

desc 'Default task: build site'
task :default => :build

desc 'Build site'
task :build do
  sh 'bundle exec middleman build'

desc 'Package site'
task :package => :build do
  sh "tar --xform 's/^\./#{directory_name}/' -cf #{file_name} -C build ."
  sh "tar -tf #{file_name}"

desc 'Cleanup: Remove build directory and *.tar.gz and *.zip files'
task :clean do
  rm_rf 'build/'
  rm_f Dir.glob('*.tar.gz')
  rm_f Dir.glob('*.zip')

With this Rakefile available, you can build your mock-up with the following command.

rake build

To create an archive you can send to your customer, run this command. It will run the build-task before it creates the package file.

rake package

To remove all built files including the package file, run the clean-task.

rake clean


middleman is really a great tool to build mock-ups. It doesn’t have a steep learning curve and is very easy to extend with pure Ruby, but also with rack-middlewares.

Using the local_webserver mentioned above makes it much easier to give away a mock-up and it doesn’t require to setup a full blown web server stack which needs to be reachable by your customers.

If you find this article interesting, you might want to read this one, too. It’s about serving local directories via HTTP using the local_webserver.

Thanks for reading!


If you found a mistake in this article or would like to contribute some content to this article, please file an issue in this Git Repository


The contents of this article are put together to the best of the authors' knowledge, but it cannot be guaranteed that it's always accurate in any environment. It is up to the reader to make sure, that all information found in this article, does not do any damage to the readers's working environment or whereever this information is applied to. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, arising from, out of or in connection with this article. Please also note the information given on the Licenses' page.

Related Articles