DEV Community

loading...

Customize Frontmatter Fields in NetlifyCMS

julianrubisch
・4 min read

Recently, I was setting up a landing page for a project in Bridgetown (highly recommended!). Later on, I began adding a blog section, and since I envisioned myself creating more content, played around with NetlifyCMS as a lightweight CMS alternative.

I followed @andrewmcodes excellent tutorial here:

The rest of this post builds up on his groundwork, so if you haven't, go read it first!

Customize Frontmatter Metadata

Every blog has its own set of metadata for its posts, but most often they include a subset of

  • title
  • description
  • categories
  • tags
  • featured image
  • post author
  • publish date

A quick review of the NetlifyCMS docs revealed that they are managed by a YAML key called fields that is part of a collection definition.

Every field at the least needs to possess

  • a label (that's how NetlifyCMS will label the field)
  • a name (that's how your metadata will end up in your frontmatter), and
  • a widget (which translates roughly to the data type and determines how your field is displayed by NetlifyCMS)
  • and, depending on the chosen widget, a set of other sub-keys (consult the NetlifyCMS docs for more precise instructions)

So here's how that might look in your NetlifyCMS config.yml file:

# ...

collections:
  - name: blog
    # ...
    fields:
      - { label: Layout, name: layout, widget: hidden, default: post }
      - { label: Title, name: title, widget: string }
      - { label: Description, name: description, widget: text }
      - { label: Featured Image, name: image, widget: image }
      - { label: Categories, name: categories, widget: list }
      - label: Author
        name: author
        widget: object
        fields:
          - {label: Name, name: name, widget: string}
          - {label: Email, name: email, widget: string}
      - { label: Publish Date, name: date, widget: datetime }
      - { label: Body, name: body, widget: markdown }

Observe that the author field uses a widget of type object, which necessitates to define which fields that object (the YAML key/value pairs that make up this field) includes. After committing these configuration changes, your post editor might look like this:

Metadata in NetlifyCMS

Referencing Authors

We can do better though, than to manually add an author's name and email every time. Imagine your blog has a couple dozen authors, you're quickly going to mistype something and sabotage any backlinks to the author. Luckily, NetlifyCMS knows a relation widget, allowing to reference a different collection.

So, let's set up an authors collection. In Bridgetown, everything you need to do is add it to your config:

collections:
  - authors

If you want, you can even have it output author pages automatically. Now we have to reference this collection in our NetlifyCMS config.yml, too:

collections:
  - name: authors
    label: Authors
    folder: src/_authors/
    extension: .md
    format: frontmatter
    create: true
    fields:
      - {label: Name, name: name, widget: string}
      - {label: Email, name: email, widget: string}

  # ...

  - name: blog
    # ...
    fields:
      # ...
      - label: Author
        name: author
        widget: relation
        collection: authors
        valueField: email
        displayFields: ["name"]
        searchFields: ["name", "email"]

The alert reader will have noticed that our collection definition resembles exactly our object definition from above. In our blog collection (shown below) we now reference the author as a relation widget, which requires a few more keys:

  • the collection
  • a valueField (which will be stored as the frontmatter value)
  • a displayFields array (the fields displayed in the UI widget), and
  • a searchFields array to allow for interactive lookup of authors.

Now for starters, let's add an author in src/_authors/julian-rubisch.md:

---
name: Julian Rubisch
email: ...
---

After a refresh, our widget now looks like this:

Author Relation Widget

If you save this post in NetlifyCMS, you will find your frontmatter filled out comfortably for you:

title: ...
description: ...
image: /images/uploads/....jpeg
categories:
  - Blog
author: .....
date: 2020-08-30T08:08:46.681Z

Render it in Bridgetown

The only remaining task is to actually render these metadata in your liquid tags, and for the new authors collection, we need a little tweak. To find the corresponding post author object out of your collection, you need to do something like

{% assign author = site.authors | where: "email", post.author | first %}
...
{{ author.name }} {{ author.email }}

in your post layout.

Bonus: A Custom Liquid Filter

To my eye, this reads clunky enough to warrant its own Liquid filter. Praise the Ruby gods, Bridgetown comes with a handy DSL to accomplish this. In plugins/builders/filter.rb, key this in:

class Filters < SiteBuilder
  def build
    liquid_filter "find_author_by_email", :find_author_by_email
  end

  def find_author_by_email(email)
    site.collections["authors"]
      .select { |author| author.email == email }
      .first
  end
end

This will allow your liquid to boil down to:

{% assign author = post.author | find_author_by_email %}
...
{{ author.name }} {{ author.email }}

Notabene: a forthcoming feature in Bridgetown will make this even easier:

Discussion (1)

Collapse
andrewmcodes profile image
Andrew Mason

Excellent explanation! Thanks!