Become a better developer.

A weekly exploration into topics to make you a better Ruby dev.

Our latest issue was about 1 month ago: Draft Blog Posts in Middleman

Draft Blog Posts in Middleman

The RubyLetter site — the one you’re reading right now — is built using the static site generator, Middleman. I really like Middleman because it feels much more fully-featured that Jekyll. However one thing that I missed from Jekyll was the drafts folder. You can put draft blog posts in _drafts and you’ll see them in development but not in production.

Middleman’s blog plugin doesn’t handle drafts nearly as well. Sure, you can put published: false in a posts frontmatter and it will be treated as a draft, but published and unpublished posts get jumbled together. It’s difficult to tell what’s published and what isn’t.

Fortunately Middleman provides us everything we need to more-or-less simulate Jekyll’s _drafts directory.

The key lies in Middleman’s ability to have multiple blogs per site.

Adding Drafts

I already had a blog set up in the /blog path. My config.rb looked something like this:

activate :blog do |blog|
  blog.prefix = "blog"
  blog.name = "blog"
  blog.layout = "article"
  blog.tag_template = "/blog/tag.html"
end

To add a “drafts” section, I simply created a new blog in the /draft path, which was only built during development:

configure :development do 
  activate :blog do |blog|
    blog.prefix = "draft"
    blog.name = "draft"
    blog.layout = "article"
    blog.tag_template = "/draft/tag.html"
  end
end

I then copied my blog/index.html and blog/tag.html templates to the draft directory and updated their frontmatter to include blog: draft. This specifies that they should pull the list of posts from the “draft” blog instead of the main blog.

Keeping Drafts Secret

Even though I told Middleman to only generate the “drafts” blog in development, it will still attempt to build and publish the posts as normal non-blog pages.

To prevent this, I needed to tell Middleman to ignore the draft directory altogether during production builds:

configure :build do 
  ignore "/draft/*"
end

And just in case the drafts ever do get deployed, I added a line to my robots.txt file to prevent them from being indexed:

User-Agent: *
Disallow: /draft

A Draft UI

Finally, I added a navbar link to my new draft blog that is only shown during development:

<% if development? %>
  <li class="nav-item pull-xs-right">
    <a class="nav-link <%= current_page.path.match(/^draft/) ? "active" : "" %>" href="/draft">Draft</a>
  </li>
<% end %>

Parting Words

I’m finally happy with the RubyLetter drafts system! It’s easy to see which posts have been published and which haven’t. It’s easy to find the draft posts in the UI.

Now, time to find something else to gripe about!

Get our weekly email about topics that will make you a better engineer. (Newest: The Network)