Dev Series #2

JSON Feed Template for Middleman

Welcome to Dev Series #2.

In this edition I cover how I added JSON Feed support to this website. JSON Feed is essentially RSS but as JSON instead of XML. In their words:

JSON is simpler to read and write, and it’s less prone to bugs.

At the outset I knew I wanted to do a couple things. Start by making a template for Middleman’s blog as a proof of concept. Then from there, figure out how to add JSON Feed support to this website.

JSON Feed: Middleman’s Blog Extension

I don’t use Middleman’s official blog extension (gem “middleman-blog”) but I started there because I figured it would be straightforward to build a JSON Feed template for it. I was right. I created a new Middleman website with blog support:

middleman init MY_BLOG_PROJECT --template=blog

Middleman includes an RSS feed template ‘feed.xml.builder’. I used it as a reference to build ‘feed.json.erb’. ERB is Middleman’s default templating language and while not the most elegant, it gets the job done. Armed with the JSON Feed spec, I came up with this:

{
  <% base_url = "https://example.org" %>
  "version": "https://jsonfeed.org/version/1",
  "title": "My Example Feed",
  "home_page_url": "<%= base_url %>",
  "feed_url": "<%= base_url + "/feed.json" %>",
  "items": [
    <% articles = blog.articles[0...5]; articles.each_with_index do |article, index| %>
    {
      "id": "<%= base_url + article.url %>",
      "url": "<%= base_url + article.url %>",
      "title": <%= article.title.to_json %>,
      "date_published": "<%= article.date.to_datetime.rfc3339 %>",
      "content_html": <%= article.body.to_json %>
    }<%= "," unless articles.size - 1 == index %>
    <% end %>
  ]
}

JSON Feed: Middleman’s Sitemap

I wanted to create a couple feeds: one for my newsletter and one for my Dev Series which you’re reading right now. For each I used Middleman’s Sitemap to find the respective items to include. The only addition I made to the individual pages was defining 'date_published' in the frontmatter.

Here’s the template I used:

{
  <% base_url = "http://shawnbaden.com" %>
  "version": "https://jsonfeed.org/version/1",
  "title": "Shawn Baden’s Dev Channel",
  "home_page_url": "<%= base_url + '/dev' %>",
  "feed_url": "<%= base_url + '/feeds/dev.json' %>",
  "author": {
    "name": "Shawn Baden",
    "url": "http://shawnbaden.com"
  },
  "items": [
    <% resources = sitemap.resources.select{ |resource| resource.path =~ /^dev\/series\/[0-9]+\/index.html$/ } %>
    <% resources.sort_by { |resource| resource.metadata[:page][:date_published]}.reverse.each_with_index do |resource, index| %>
    {
      "id": "<%= base_url + resource.url %>",
      "url": "<%= base_url + resource.url %>",
      "title": <%= resource.metadata[:page][:title].to_json %>,
      "date_published": "<%= resource.metadata[:page][:date_published].to_s%>",
      "content_html": <%= resource.metadata[:page][:title].to_json %>
    }<%= "," unless resources.size - 1 == index %>
    <% end %>
  ]
}

Originally published June 2, 2017