Implementing a Blog Series in Middleman

While working on my hammerspoon series, I decided it was a good time to refactor how I related a series of blog posts. Over the past year or two, I’ve found myself doing a series of shorter posts rather than one long monster post.

I first implemented this for my series on Git Gud at Vim. I simply used a markdown comment that I copy pasted at the top of every post, and a tag git-gud-vim that I used to link them all together. It worked just fine, and I did the same for the World of Textfiles posts.

While working on the Hammerspoon Headspace series, I wanted to do a little more styling, and realized quickly that I probably could do something a little more comprehensive. Still using tags, I just wrote some custom logic conditional on a tag that started with series-. If a post had a tag prefixed with series-, it’d look in a folder for a partial named the same way and include it.

This was of course a dreadful kluge, but it got me a single partial I could use in several places… so every post could be updated all at the same time.

Eventually I dug further into middleman’s docs and found their custom collections feature. This meant that I could create custom YAML attribute and fire off some logic much more simply.

First initialize the custom collection…

activate :blog do |blog|
  blog.tag_template = 'tag.html'
  blog.calendar_template = 'calendar.html'
  blog.custom_collections = {
    series: {
      link: '/series/{series}.html',
      template: '/articles/series/show.html'
    }
  }
end

Now I just built a quick helper in config.rb to grab the content from the partial. There may be a better way to do this… but this worked.

def series_header(series, is_index: false)
    header = is_index ? "<h1>#{series}</h1>" : ""
    return %{
    #{header}
    <div class="article__series">
      #{partial("articles/series/#{slugify(series)}")}
      <div class="blog__tags">
        <span class="tag__emoji">🗂</span>
        <a href="/articles/series/#{slugify(series)}">
          #{series}
        </a>
      </div>
    </div>
    }
end

Now I can use this on the series show page, the series listing page, or any single page in a series… I can update the series display, or the content, and it updates everywhere.

I love being able to build my website into whatever I want… hopefully even if I leave middleman I can take the content I wrote for the series headers with me.