For nearly seven years I was a CMS implementer and contributor, mostly with Drupal, but occasionally with Joomla! and WordPress. Then about 3 years ago I encountered Jekyll and I had a revelation, a system that let me manage and render content, but in a manner that suited me as a writer, using markup formats such as markdown, reStructuredText, and Asciidoc. Whilst the plain text and version control approach is great for some, and despite best efforts from vendors such as GitHub and GitLab, it’s still not that accessible to less technically minded people. Many projects have attempted to bridge this gap and merge the best of the two worlds, from commercial SaaS providers such as Contentful, Prismic, or CloudCannon to open source options like Cockpit and getmesh.

Just over a year ago, Netlify, the fantastic host for static sites announced ‘Netlify CMS’ and it looked promising, adding a CMS-like interface to the git workflow. I made some initial investigations, but now finally have time for a proper dive into how to set it up and use it.

I will use Netlify CMS (NC) with Jekyll, but you can find instructions on how to add it to other existing static sites or get started from scratch with a new site.

Adding Netlify CMS to Jekyll

Create an admin folder with an index.html and a config.yml file; these act as the gateway to your admin interface and the settings behind it, respectively.

Inside index.html, add the skeleton HTML, JavaScript, and CSS needed to create the admin interface, for full custom branding, you can add links to your style sheets too, but as this is an admin ‘backend,’ you may not need them.

<!doctype html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Content Manager</title> <!-- Add your own styles here --> <link rel="stylesheet" href="https://unpkg.com/netlify-cms@^1.0.0/dist/cms.css" /> </head> <body> <!-- Include the script that builds the page and powers Netlify CMS --> <script src="https://unpkg.com/netlify-cms@^1.0.0/dist/cms.js"></script> </body> </html>

Naturally, the configuration file varies for your use case, but I’ll show you what I use for my ‘Gregarious Mammal’ site, and you can extrapolate from there.

First, determine the backend type and if users need to authenticate to access it, you can use users defined in Netlify, or in GitHub (those with push access). I want to allow users to change content outside of Netlify, so use the GitHub method:

backend: name: github repo: GregariousMammal/Main-Site # Path to Github repository branch: master # Branch to update

To define which users can access the admin backend and edit content I recommend you read Netlify’s steps. You can authenticate with a variety of different methods, or handle the process via Netlify’s identity service that you might have setup already (I do).

If you add the setting below, then posts go through a workflow process where specific users can review and edit posts held in pull requests until you publish them. Otherwise, NC commits posts to the branch defined above.

publish_mode:editorial_workflow

The site uses lots of images, and I want people to add an image with every post, so you need to define where to store them, add that with the media_folder parameter, and also public_folder that sets where to serve images from:

media_folder:"images"# Media files will be stored in the repo under images public_folder:"/images"# The src attribute for uploaded media will begin with /images

I did find some issues with images I had stored in sub-folders, there is an issue discussing sub-folders, but I’m unsure if it’s related.

Now comes the most complicated part. My site has a lot of different ‘content types’ to represent different items of content, sometimes using collections and sometimes using different fields in different places. This section will be the section of your configuration and consists of a series of YAML sections representing your content. The general structure is:

collections: - name: "posts" # Used in routes, e.g. /admin/collections/blog label: "Posts" # Used in the UI folder: "_posts" # The path to the folder where the documents are stored create: true # Allow users to create new documents in this collection slug: " {{year}} - {{month}} - {{day}} - {{slug}} " # Filename template i.e. YYYY-MM-DD-title.md filter: - field: publication_url - value: "" fields: # The fields for each document, usually in front matter - {label: "Layout", name: "layout", widget: "hidden", default: "post"} - {label: "Title", name: "title", widget: "string"} - {label: "Publish Date", name: "date", widget: "datetime"} - {label: "Featured Image", name: "image", widget: "image"} - {label: "Categories", name: "categories", widget: "string"} - {label: "Tags", name: "tags", widget: "string"} - {label: "Body", name: "body", widget: "markdown"} - {label: "Publication URL", name: "publication_url", widget: "string"}

You can use one of about 12 default widgets, and it’s not too hard to create your own if you know React. By default, fields are set as required , so add required: false if they are not in your content model, i.e.:

-{label: "Publication URL", name: "publication_url", widget: "string", required: false}

My site has a lot of content, and I couldn’t get Netlify CMS to load it all - this might be limits with JavaScript calls or the GitHub API. There’s probably a way to fix this, but as a lot of the posts are autogenerated stub files for aggregated content, I don’t need to edit them anyway. Netlify CMS offers a way to filter these using the filter property on a field value.

filter: - field: language - value: en

I wanted to filter by date to load the most recent posts, but that wasn’t possible, so I tried to filter posts that didn’t have a publication_url but didn’t have much luck getting filters to work, your mileage may vary. There are also limits on how much you can pull from the GitHub API, so I might need to reorganize my content into more collections or sub-folders.

You can see the complete content types for my site here.

Using Netlify CMS

Fire up your static site generator as normal and visit _admin. You should see sections for each of the content types you defined, plus one for media and workflow (if enabled).

The interface has limited filter and sort options, but there is a search box. You use the add buttons to create content with a handy GUI and preview it. When you click save, posts are held in a pull request until you publish them when they are then merged into the master. There’s a summary here of what GUI action results in what git action.

SSCMS (Static Site CMS!)

In my opinion, Netlify has, so far, made the best effort to create a CMS-like front-end for static sites that suits the workflows of technical and non-technical users. It’s early days with bugs and features needed, but with the strength of the Netlify commercial product and community drive, I hold a lot of hope for its development.