Turning Netlify CMS Up to Eleventy
by Wayne Thursby
This guide will help you get started using Netlify CMS with Eleventy. This will set up a very basic blog site and is intended as a demonstration of the concepts.
If you just want to get up and running quickly, a vastly superior site can be had in just a few seconds by using the Eleventy Netlify Boilerplate project. The Deploy to Netlify button does what it says, and quite literally couldn't be easier. This guide borrows heavily from that work, but is simplified for illustrative purposes.
Objectives
- Create a functional website following the pattern of a blog.
- The site should have Pages and Posts.
- Features such as tags and contact forms are beyond the scope of this article.
Create a basic Eleventy site
First, install Eleventy as usual. See the Eleventy Getting Started guide for more information.
Create directories for resources.
mkdir -p admin pages posts static/img _includes/layouts
For this site we simply want the ability to use Netlify CMS to edit Pages if necessary, and add Posts regularly. One of the pages will need to feature the available posts.
To keep things simple, we will not be using other basic features of Eleventy to do things like include headers or footers.
Create the base layout
The base layout will be the general HTML structure used by the entire site, and should be as content-agnostic as possible. Typically several includes would be used, but this is a simple example.
_includes/layouts/base.njk
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title or renderData.title or metadata.title }}</title>
<script async src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
</head>
<body>
<header>
<em>
<a href="{{ '/' | url }}">Awesome Blog</a>
</em>
</header>
<main>
{{ layoutContent | safe }}
</main>
</body>
</html>
Now that the basic HTML has been defined, let's create a few quick variations for our Home page, other Pages, as well as our blog Posts. These will all inherit from other layouts, so they will be simple to create.
_includes/layouts/home.njk
---
layout: layouts/base.njk
section: home
---
{{ layoutContent | safe }}
_includes/layouts/page.njk
---
layout: layouts/base.njk
section: page
---
<h1>{{ title }}</h1>
{{ layoutContent | safe }}
The Posts layout is slightly more complex, but that's because this is where the content is being displayed.
_includes/layouts/post.njk
---
layout: layouts/base.njk
section: post
---
<article>
<h1>{{ title }}</h1>
<p>
<small><time datetime="{{ date | machineDate }}">{{ date | readableDate }}</time> by {{ metadata.author.name }}</small>
</p>
{{ layoutContent | safe }}
</article>
<nav>
<a href="{{ '/blog/' | url }}">← Blog index</a>
</nav>
One last thing
We can't expect our end users to set all of the fields required to publish content. Any fields we want to set for a directory may be specified in a JSON file in each directory.
pages/pages.json
{
"layout": "layouts/page.njk"
}
posts/posts.json
{
"layout": "layouts/post.njk",
"permalink": "posts/turning-netlify-cms-up-to-eleventy/index.html",
"tags": "post"
}
Welcome Home
You're all set to create your new home! Posts will be able to be created from within Netlify CMS, but Pages will be created manually. After they're created you can edit them from within the CMS.
pages/home.md
---
layout: layouts/home.njk
title: Home
date: 2019-06-29T00:00:00.000Z
permalink: /
navtitle: Home
tags:
- nav
---
# Welcome to Home
This is my home page. Welcome.
See it in action
You can run Eleventy to generate our site locally. It's still rather impressive, but this will just make sure it all works.
npx eleventy
If you're getting any errors at this point, check to make sure you've not upset the JSON deities with an errant comma.
Wire up NetlifyCMS
The NetlifyCMS admin interface is a React app, and therefore may be as a simple as a single HTML file which loads from a CDN. We are also using the Netlify Identity service, so that resource should also be loaded here as well as everywhere else on the site.
admin/index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Content Manager</title>
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
</head>
<body>
<!-- Include the script that builds the page and powers Netlify CMS -->
<script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
</body>
</html>
Now create a config.yml that reflects the layout of our files, as well as the fields we want to show from the frontmatter. This can look complex, but if you look closely, you'll see it's actually a fairly simple description of what fields you want to edit.
admin/config.yml
backend:
name: git-gateway
branch: master # Branch to update (optional; defaults to master)
# Uncomment below to enable drafts
# publish_mode: editorial_workflow
media_folder: "static/img" # Media files will be stored in the repo under images/uploads
collections:
# Our blog posts
- name: "blog" # Used in routes, e.g., /admin/collections/blog
label: "Post" # 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: "" # Filename template, e.g., YYYY-MM-DD-title.md
fields: # The fields for each document, usually in front matter
- { label: "Title", name: "title", widget: "string" }
- { label: "Publish Date", name: "date", widget: "datetime" }
- { label: "Summary", name: "summary", widget: "text" }
- { label: "Tags", name: "tags", widget: "list", default: ["post"] }
- { label: "Body", name: "body", widget: "markdown" }
# Our pages e.g. About
- name: "pages"
label: "Page"
folder: "pages"
create: false # Change to true to allow editors to create new pages
slug: ""
fields:
- { label: "Title", name: "title", widget: "string" }
- { label: "Publish Date", name: "date", widget: "datetime" }
- { label: "Permalink", name: "permalink", widget: "string" }
- { label: "Navigation Title", name: "navtitle", widget: "string" }
- { label: "Tags", name: "tags", widget: "hidden", default: "nav" }
- { label: "Body", name: "body", widget: "markdown" }
Set up a repository
Saving your code in a repository is a nice recommendation for most projects, but for this one it is essential. The repository will be the data store as well as the start of the build process.
The easiest to use is GitHub, so start by creating a GitHub repository and checking it out to your dev environment.
Next, create a new site on Netlify using the newly created repository.
Provide editor access
Netlify's Identity service acts as a proxy between your repository and any of several identity sites. This means you can invite users through Google and other identity providers without giving them access to the repository.
To configure this feature. Enable the Netlify identity service and Git Gateway on the deployment.
- Settings > Identity
- Select Enable Identity service
- Scroll down to Services > Git Gateway, and click Enable Git Gateway
- Accept the defaults and proceed. See the Netlify Identity documentation for more info.
Now log in at /admin/ and create some posts!