Supercharge Your Bridgetown Site with Ruby Front Matter

Jared White Jared White on May 5, 2020

Starting in Bridgetown v0.13, you can now write real Ruby code directly in your Front Matter! 🤯 This feature is available for pages, posts, and other documents–as well as layouts for site-wide access to your Ruby return values.

Now you may be wondering, how is this even possible? Front Matter is in YAML format, and the only place you can write actual code is in a custom plugin, right? RIGHT??

Well…it just so happens that there’s this nifty bit of the YAML specification which allows for serialization and deserialization of objects. Normally that functionality is switched off in Bridgetown for security reasons. But we figured out a way to punch a hole through this security barrier to allow for a special type of string that represents Ruby code. It looks like this:

---
title: I'm a page
permalink: /ruby-demo
calculation: !ruby/string:Rb |
  [2 * 4, 5 + 2].min
---

Title: {{ page.title }}
Calc Result: {{ page.calculation }}

In this example, the value of the calculation variable is the return value of the Ruby code defined by the special string !ruby/string:Rb. The | symbol at the end just means all the indented code in the line(s) below are attached to that front matter variable.

The value printed out in the rendered page for the calculation will be 7 (since 7 is less than 8 and thus the minimum integer in the array). In fact, on this very page you’re reading, that number 7 is actually being generated by Ruby Front Matter, not hard-coded in this article! Thus you know the system works. ☺️

In Ruby Front Matter you can return any kind of value that is accessible from a Liquid template. So strings, numbers, arrays, hashes, integers: they all work. Even objects can be returned if they are implemented as a Liquid drop.

You can also access other Front Matter variables from within the Ruby code itself.

---
title_fragment: Title of a Page
title: !ruby/string:Rb |
  "This is the #{data["title_fragment"].sub("Title", "Name")}"
---

Now the page title will read: This is the Name of a Page

Use Cases for Ruby Front Matter

One particularly compelling use case for Ruby Front Matter is to load data in from a third-party source for inclusion on a page (typically in JSON format, but it could be anything really). Here’s an example of loading a file from a remote GitHub repository and parsing it to obtain useful information:

---
seo_tag_gem_version: !ruby/string:Rb |
  url = "https://raw.githubusercontent.com/bridgetownrb/bridgetown-seo-tag/master/lib/bridgetown-seo-tag/version.rb"
  result = Faraday.get(url).body
  result.match(/VERSION = "(.*?)"/)[1]
---

This will pull the current gem version of the master branch from bridgetown-seo-tag and output it via {{ page.seo_tag_gem_version }} (it’s 3.0.5).

Another example is a feature we include on this very website’s footer to show the average number of commits to the Bridgetown project on GitHub over the past month. (At the time this site was last built, that number is **.)

Here’s the Ruby Front Matter we include in _layouts/default.html:

---
github_participation: !ruby/string:Rb |
  endpoint = "https://api.github.com/repos/bridgetownrb/bridgetown/stats/participation"

  conn = Faraday.new(
    url: endpoint,
    headers: {"Accept" => "application/vnd.github.v3+json"}
  )
  if ENV["BRIDGETOWN_GITHUB_TOKEN"]
    username, token = ENV["BRIDGETOWN_GITHUB_TOKEN"].split(":")
    conn.basic_auth(username, token)
  end
  json = JSON.parse(conn.get.body)
  json["all"][-4..].sum
---
<!doctype html>
…etc…

Then in our footer (or anywhere on the site), we simply add {{ layout.github_participation }} to output that value.

Caveats and Takeaways

If you need to write a lot of Ruby code, or write code that is easily customizable or reusable in multiple contexts, we still recommended you write a Bridgetown plugin—either in the plugins folder in your site repo or as a separate Gem-based plugin.

But if you just need to add a little bit of dynamic functionality to a page or a layout and like being able to see the code and content combined into a single file, Ruby Front Matter is a powerful and immensely flexible solution.

And remember, this isn’t a “lite” or stripped-down version of Ruby. This is 100% full Ruby. So you can process page or site data, instantiate objects, require gems, perform network requests, interact with the underlying filesystem, monkeypatch and metaprogram and do anything you’d ever need to do via Ruby.

In summary, if you’re excited to give Ruby Front Matter a try, all you have to do is install Bridgetown v0.13 or later, set BRIDGETOWN_RUBY_IN_FRONT_MATTER to "true" in your development environment, and go to town (Bridge…town 😋). And be sure to share your sweet solutions on Twitter with the hashtag #SpinUpBridgetown to let the community know what you’ve built with Ruby Front Matter!

(Also learn which internal Bridgetown objects are made available to your Ruby code in the documentation here.