[005.2] Middleman Data and Extensions

Installing extensions into Middleman, and using Middleman Data

Subscribe now

Middleman Data and Extensions [07.17.2017]

Today we are going to continue exploring the Middleman framework. We'll start off looking at a couple of common extensions to make development easier, then move into discussing the Data toolset inside of Middleman. The theme for today is easier front end development, and everything we look at will make your front end coding tasks easier.

General Setup

When I'm working on a static front end project, my setup in generally pretty simple. I use a desktop that holds my code and a second monitor that has Chrome (or whatever other browsers I'm working with) on it. When I'm just on my laptop or recording, like now, I split-screen both of those onto a single screen. This combined with livereload allows me in real-time to see how my code is rendering. Additionally I use a hot-key terminal with two tabs opened to the directory I'm working in. The first tab is the server and the second is my utility tab, where I make git commits and that kind of thing.

Live Reload

I just mentioned livereload and it is a great tool. When in development, it tells your browser to connect a web socket, and monitors your local file structure. Whenever a change is detected, your browser then reloads and re-applies those changes in as smart a way as possible. For example, if you just change some CSS rules, then it'll just reload the CSS. If you change your javascript then that gets reloaded. Live reload only makes full page loads when absolutely necessary.

This allows you to continually write code while seeing the changes quickly. You won't have to go back to the browser and refresh constantly. The best part is how easy to install it is.

The first thing we'll do is add the gem to our Gemfile then run bundle to install it.

Gemfile:

gem "middleman-livereload"

In the shell:

bundle

Now let's add these two lines to our config.rb so Middleman knows about Live Reload.

config.rb:

# Live Reload
activate :livereload

Now we just start Middleman with middleman and we can see that as we make changes, they are applied quickly in the browser without the need for us to refresh.

If you want to dive into how this works, just view your source and you can browse to the livereload javascript file and settings that gets added to our head node.

Autoprefixer

Autoprefixer describes itself as a:

PostCSS plugin to parse CSS and add vendor prefixes to CSS rules using values from Can I Use.

That's a lot to unpack, so let's take it step by step. PostCSS is a javascript toolset that transforms your CSS during a build process. It can do things like lint, transpile, inline images, and much much more. In the case of Autoprefixer, it is being used to add browser specific prefixes to CSS rules as needed.

It uses a database from Can I Use, which is essentially a giant matrix of every possible CSS property by all in-use browsers. It knows what properties work where, and which properties need vendor specific prefixes. After installing the Autoprefixer plugin, Middleman will automatically add prefixes everywhere needed, so you don't have to.

Autoprefixer comes with new installs of Middleman, so it's already in our example project, rudiment. But just in case you don't have it in your project, setting it up is easy -- just add the gem, run bundle to install, drop in a few lines of configuration and start the server.

Gemfile:

gem 'middleman-autoprefixer'

In the shell:

bundle

config.rb:

# Autoprefixer setup, uses same options as
# https://github.com/postcss/autoprefixer#browsers
activate :autoprefixer do |prefix|
  prefix.browsers = "last 2 versions"
end

Now when we browse to our local stylesheet we see that around the flexbox info in the bottom half of the file, we have a lot of prefixes added for us automatically. This is another big time saver, and it has the bonus of keeping your source CSS files much more maintainable.

Data Files

Now that our environment is much easier to work in, lets take a look how Middleman works with data files, and how you can use them to make your dev work a lot easier. By default, there is support for .yaml and .json file types. As a rule, I stick with json files for a handful of reasons. First JSON is a more universal format. I'm more likely to have the data stores in JSON already. Second JSON is a much simpler spec and most devs already know JSON, easier onboarding is a big deal.

If you look at our index.html.erb from before, you'll notice that we're already using a bit of the data tools. We set a title and footer, then call it in both the index page as well as the layout.

Setup is trivial: just drop json files into the data folder, naming them without spaces or special characters. If you are constructing those files by hand be sure to take a moment and lint the JSON with one of the many online tools. I like JSONlint. One note: you will need to restart your middleman server after creating a new data file. After that, livereload will detect changes and reload properly.

Let's get started by creating a new file: data/example.json. Inside of it I'll go ahead and put a dozen items in a list.

{
  "list": [
    "One",
    "Two",
    "Three",
    "Four",
    "Five",
    "Six",
    "Seven",
    "Eight",
    "Nine",
    "Ten",
    "Eleven",
    "Twelve"
  ]
}

Now we have access to this information via the data function. You call it like you would a Proc in Ruby. Let's see what this is like by dumping the list before our menu in the left sidebar.

<menu>
  <p><%= data.example.list %></p>
  <ul>
    <!-- snip -->

That's great we can drop text on a page, but a raw array doesn't do us a lot of good. We can take this a step further by looping through the items, and rendering a block of code for each one.

<menu>
  <ul>
    <%- data.example.list.each do |item| %>
      <li><a href="#"><%= item %></a></li>
    <%- end %>
  </ul>
</menu>

We've rendered a menu entry for each item in our array. This is starting to look useful! now let's look at a more complicated example from a different repository. The webpage for Firestorm, our Elixir based open source forum, is written using Middleman. We have a Patrons Section for all those lovely individuals that donated to our Kickstarter. Rather than directly coding all the potential links and images, we use Data to manage them.

We can see our datafile on Github as well as our layout that calls them. We use nested hashes to pass named parameters to the view, and render out a really complex piece of markup from some very simple code.

Note that this is written in HAML, an HTML abstraction that we'll look at in detail soon.

Here is the JSON template we send to the view.

{
  "name": "DailyDrip",
  "image_file": "patron-dailydrip.png",
  "url": "https://www.dailydrip.com",
  "icons": [
    ["github-alt", "https://github.com/dailydrip"],
    ["twitter", "http://www.twitter.com/dailydripcom"],
    ["facebook", "http://facebook.com/dailydripcom"]
  ]
}

And the template that renders it.

- data.patrons.patron_saints.each do |patron_saint|
  %figure.pure-u-1-2.pure-u-lg-1-3.patron
    = link_to patron_saint[:url] do
      = image_tag image_path(patron_saint[:image_file])
    %figcaption
      = link_to patron_saint[:url] do
        = patron_saint[:name]
      %ul.patron-icons
        %li
          = link_to patron_saint[:url] do
            %i.fa.fa-globe
        - patron_saint[:icons].each do |icon, url|
          %li
            = link_to url do
              %i.fa{class: "fa-#{icon}"}

We loop through the array, rendering a name and image for each image file. We link those to the patron's site, as well as dynamically render the proper icon and link.

Data files are really flexible, and allow for some neat tricks. In one instance we use strings containing markdown to render a formatted list of links for each patron. This is much easier than managing this page manually!

Summary

Today we looked at installing and using a couple simple extensions to Middleman. First up was livereload, so we can see our pages evolve as we code. Next was autoprefixer to keep our output CSS files friendly to all the browses.

Finally, we looked at how to use data files in Middleman. Managing a site via data files can be as simple as generating a JSON file. We can update our site without having to alter any code. I've used this to great effect by having a service that outputs JSON, then an automated build process that generates and publishes a site to a hosting platform like S3. You can easily have fully 'dynamic' sites that have up to date information (like product availability) but still host in a fully static environment.

Resources