Start with a Template

You can add Netlify CMS to an existing site, but the quickest way to get started is with a template. Found below, our featured templates deploy a bare-bones site and Netlify CMS to Netlify (what’s the difference, you ask?), giving you a fully working CMS-enabled site with just a few clicks.

After clicking one of those buttons, authenticate with GitHub or GitLab and choose a repository name. Netlify then automatically creates a clone of the repository in your GitHub or GitLab account. Next, it builds and deploys the new site on Netlify, bringing you to the site dashboard after completing the build.

Note for Bitbucket users: Netlify CMS supports Bitbucket repositories, but Bitbucket’s permissions won’t work with the Deploy to Netlify buttons above. You can still set up a repository manually, or follow the tutorial for adding Netlify CMS to an existing site.

Access Netlify CMS on your new site

  1. The template deploy process sends you an invitation to your new site, sent from [email protected]. Sample email subject line: You've been invited to join radiologist-amanda-53841.netlify.com
  2. Wait for the deployment to complete, then click the link to accept the invite. Your site will open with a prompt to create a password.
  3. Enter a password, sign in, and you’ll go to the CMS. (For future visits, you can go straight to <yoursiteaddress.com>/admin/.)

Try adding and editing posts, or changing the content of the Products page. When you save, the changes are pushed immediately to your Git repository, triggering a build on Netlify, and updating the content on your site. Check out the configuration code by visiting your site repo.

More paths to explore

  • To see how to integrate Netlify CMS into an existing project, go to Add to your site.
  • Check out other sites using Netlify CMS (or share your own!) on the Examples page.
  • If you’d like to add more CMS editors or change how they log in to your site, read up on Netlify Identity service.

Collection Types

All editable content types are defined in the collections field of your config.yml file, and display in the left sidebar of the Content page of the editor UI.

Collections come in two main types: folder and files.

Folder collections

Folder collections represent one or more files with the same format, fields, and configuration options, all stored within the same folder in the repository. You might use a folder collection for blog posts, product pages, author data files, etc.

Unlike file collections, folder collections have the option to allow editors to create new items in the collection. This is set by the boolean create field.

Note: Folder collections must have at least one field with the name title for creating new entry slugs. That field should use the default string widget. The label for the field can be any string value. If you wish to use a different field as your identifier, set identifier_field to the field name. See the Collections reference doc for details on how collections and fields are configured. If you forget to add this field, you will get an error that your collection “must have a field that is a valid entry identifier”.

Example:

collections:
  - label: "Blog"
    name: "blog"
    folder: "_posts/blog"
    create: true
    fields:
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Featured Image", name: "thumbnail", widget: "image"}
      - {label: "Body", name: "body", widget: "markdown"}

With identifier_field:

- label: "Blog"
  name: "blog"
  folder: "_posts/blog"
  create: true
  identifier_field: name
  fields:
    - {label: "Name", name: "name", widget: "string"}
    - {label: "Publish Date", name: "date", widget: "datetime"}
    - {label: "Featured Image", name: "thumbnail", widget: "image"}
    - {label: "Body", name: "body", widget: "markdown"}

Filtered folder collections

The entries for any folder collection can be filtered based on the value of a single field. By filtering a folder into different collections, you can manage files with different fields, options, extensions, etc. in the same folder.

The filter option requires two fields:

  • field: The name of the collection field to filter on.
  • value: The desired field value.

The example below creates two collections in the same folder, filtered by the language field. The first collection includes posts with language: en, and the second, with language: es.

collections:
  - label: "Blog in English"
    name: "english_posts"
    folder: "_posts"
    create: true
    filter: {field: "language", value: "en"}
    fields:
      - {label: "Language", name: "language", widget: "select", options: ["en", "es"]}
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Content", name: "body", widget: "markdown"}
  - label: "Blog en Español"
    name: "spanish_posts"
    folder: "_posts"
    create: true
    filter: {field: "language", value: "es"}
    fields:
      - {label: "Lenguaje", name: "language", widget: "select", options: ["en", "es"]}
      - {label: "Titulo", name: "title", widget: "string"}
      - {label: "Contenido", name: "body", widget: "markdown"}

Nested collections (beta)

Nested collections is a beta feature that allows a folder collection to show a nested structure of entries and edit the locations of the entries. This feature is useful when you have a complex folder structure and may not want to create separate collections for every directory. As it is in beta, please use with discretion.

File collections

A files collection contains one or more uniquely configured files. Unlike items in folder collections, which repeat the same configuration over all files in the folder, each item in a files collection has an explicitly set path, filename, and configuration. This can be useful for unique files with a custom set of fields, like a settings file or a custom landing page with a unique content structure.

When configuring a files collection, configure each file in the collection separately, and list them under the files field of the collection. Each file has its own list of fields and a unique filepath specified in the file field (relative to the base of the repo).

Note: Files listed in a file collection must already exist in the hosted repository branch set in your Netlify CMS backend configuration. Files must also have a valid value for the file type. For example, an empty file works as valid YAML, but a JSON file must have a non-empty value to be valid, such as an empty object.

Example:

collections:
  - label: "Pages"
    name: "pages"
    files:
      - label: "About Page"
        name: "about"
        file: "site/content/about.yml"
        fields:
          - {label: Title, name: title, widget: string}
          - {label: Intro, name: intro, widget: markdown}
          - label: Team
            name: team
            widget: list
            fields:
              - {label: Name, name: name, widget: string}
              - {label: Position, name: position, widget: string}
              - {label: Photo, name: photo, widget: image}
      - label: "Locations Page"
        name: "locations"
        file: "site/content/locations.yml"
        fields:
          - {label: Title, name: title, widget: string}
          - {label: Intro, name: intro, widget: markdown}
          - label: Locations
            name: locations
            widget: list
            fields:
              - {label: Name, name: name, widget: string}
              - {label: Address, name: address, widget: string}

Releases

Update the CMS Version

The update procedure for your CMS depends upon the method you used to install Netlify CMS.

Package Manager

If you are using a package manager like Yarn or NPM, use their standard procedure to update. This is how both the Hugo and Gatsby starters are set up.

CDN

If you are using the CMS through a CDN like Unpkg, then that depends on the version tag you are using. You can find the version tag in the /admin/index.html file of your site.

  • (Recommended) If you use ^2.0.0, the CMS does all updates except major versions automatically.
    • It upgrades to 2.0.1, 2.1.0, 2.1.2.
    • It does not upgrade to 3.0.0 or higher.
    • It does not upgrade to beta versions.
  • If you use ~2.0.0, the CMS will do only patch updates automatically.
    • It upgrades 2.0.1, 2.0.2.
    • It does not upgrade to 2.1.0 or higher.
    • It does not upgrade beta versions.

Add to Your Site

You can adapt Netlify CMS to a wide variety of projects. It works with any content written in markdown, JSON, YAML, or TOML files, stored in a repo on GitHub, GitLab, or Bitbucket. You can also create your own custom backend.

This tutorial guides you through the steps for adding Netlify CMS to a site that’s built with a common static site generator, like Jekyll, Hugo, Hexo, or Gatsby. Alternatively, you can start from a template or dive right into configuration options.

App File Structure

A static admin folder contains all Netlify CMS files, stored at the root of your published site. Where you store this folder in the source files depends on your static site generator. Here’s the static file location for a few of the most popular static site generators:

These generators store static files in
Jekyll, GitBook / (project root)
Hugo, Gatsby, Nuxt 2, Gridsome, Zola, Sapper /static
Next, Nuxt 3 /public
Hexo, Middleman, Jigsaw /source
Spike /views
Wyam /input
Pelican /content
VuePress /.vuepress/public
Elmstatic /_site
11ty /_site
preact-cli /src/static
Docusaurus /static

If your generator isn’t listed here, you can check its documentation, or as a shortcut, look in your project for a css or images folder. The contents of folders like that are usually processed as static files, so it’s likely you can store your admin folder next to those. (When you’ve found the location, feel free to add it to these docs by filing a pull request!)

Inside the admin folder, you’ll create two files:

admin
 ├ index.html
 └ config.yml

The first file, admin/index.html, is the entry point for the Netlify CMS admin interface. This means that users navigate to yoursite.com/admin/ to access it. On the code side, it’s a basic HTML starter page that loads the Netlify CMS JavaScript file. The second file, admin/config.yml, is the heart of your Netlify CMS installation, and a bit more complex. The Configuration section covers the details.

In this example, we pull the admin/index.html file from a public CDN.

<!doctype html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Content Manager</title>
</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>

In the code above the script is loaded from the unpkg CDN. Should there be any issue, jsDelivr can be used as an alternative source. Simply set the src to https://cdn.jsdelivr.net/npm/netlify-cms@^2.0.0/dist/netlify-cms.js

Installing with npm

You can also use Netlify CMS as an npm module. Wherever you import Netlify CMS, it automatically runs, taking over the current page. Make sure the script that imports it only runs on your CMS page. First install the package and save it to your project:

npm install netlify-cms-app --save

Then import it (assuming your project has tooling for imports):

import CMS from 'netlify-cms-app'
// Initialize the CMS object
CMS.init()
// Now the registry is available via the CMS object.
CMS.registerPreviewTemplate('my-template', MyTemplate)

Configuration

Configuration is different for every site, so we’ll break it down into parts. Add all the code snippets in this section to your admin/config.yml file.

Backend

We’re using Netlify for our hosting and authentication in this tutorial, so backend configuration is fairly straightforward.

For GitHub and GitLab repositories, you can start your Netlify CMS config.yml file with these lines:

backend:
  name: git-gateway
  branch: master # Branch to update (optional; defaults to master)

(For Bitbucket repositories, use the Bitbucket backend instructions instead.)

The configuration above specifies your backend protocol and your publication branch. Git Gateway is an open source API that acts as a proxy between authenticated users of your site and your site repo. (We’ll get to the details of that in the Authentication section below.) If you leave out the branch declaration, it defaults to master.

Editorial Workflow

Note: Editorial workflow works with GitHub repositories, and support for GitLab and Bitbucket is in beta.

By default, saving a post in the CMS interface pushes a commit directly to the publication branch specified in backend. However, you also have the option to enable the Editorial Workflow, which adds an interface for drafting, reviewing, and approving posts. To do this, add the following line to your Netlify CMS config.yml:

# This line should *not* be indented
publish_mode: editorial_workflow

Media and Public Folders

Netlify CMS allows users to upload images directly within the editor. For this to work, the CMS needs to know where to save them. If you already have an images folder in your project, you could use its path, possibly creating an uploads sub-folder, for example:

# This line should *not* be indented
media_folder: "images/uploads" # Media files will be stored in the repo under images/uploads

If you’re creating a new folder for uploaded media, you’ll need to know where your static site generator expects static files. You can refer to the paths outlined above in App File Structure, and put your media folder in the same location where you put the admin folder.

Note that themedia_folder file path is relative to the project root, so the example above would work for Jekyll, GitBook, or any other generator that stores static files at the project root. However, it would not work for Hugo, Hexo, Middleman or others that store static files in a subfolder. Here’s an example that could work for a Hugo site:

# These lines should *not* be indented
media_folder: "static/images/uploads" # Media files will be stored in the repo under static/images/uploads
public_folder: "/images/uploads" # The src attribute for uploaded media will begin with /images/uploads

The configuration above adds a new setting, public_folder. While media_folder specifies where uploaded files are saved in the repo, public_folder indicates where they are found in the published site. Image src attributes use this path, which is relative to the file where it’s called. For this reason, we usually start the path at the site root, using the opening /.

If public_folder is not set, Netlify CMS defaults to the same value as media_folder, adding an opening / if one is not included.

Collections

Collections define the structure for the different content types on your static site. Since every site is different, the collections settings differ greatly from one site to the next.

Let’s say your site has a blog, with the posts stored in _posts/blog, and files saved in a date-title format, like 1999-12-31-lets-party.md. Each post begins with settings in yaml-formatted front matter, like so:

---
layout: blog
title: "Let's Party"
date: 1999-12-31 11:59:59 -0800
thumbnail: "/images/prince.jpg"
rating: 5
---

This is the post body, where I write about our last chance to party before the Y2K bug destroys us all.

Given this example, our collections settings would look like this in your NetlifyCMS config.yml file:

collections:
  - name: "blog" # Used in routes, e.g., /admin/collections/blog
    label: "Blog" # Used in the UI
    folder: "_posts/blog" # 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, e.g., YYYY-MM-DD-title.md
    fields: # The fields for each document, usually in front matter
      - {label: "Layout", name: "layout", widget: "hidden", default: "blog"}
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Featured Image", name: "thumbnail", widget: "image"}
      - {label: "Rating (scale of 1-5)", name: "rating", widget: "number"}
      - {label: "Body", name: "body", widget: "markdown"}

Let’s break that down:

name Post type identifier, used in routes. Must be unique.
label What the admin UI calls the post type.
folder Where files of this type are stored, relative to the repo root.
create Set to true to allow users to create new files in this collection.
slug Template for filenames. {{year}}, {{month}}, and {{day}} pulls from the post’s date field or save date. {{slug}} is a url-safe version of the post’s title. Default is simply {{slug}}.
fields Fields listed here are shown as fields in the content editor, then saved as front matter at the beginning of the document (except for body, which follows the front matter). Each field contains the following properties:

  • label: Field label in the editor UI.
  • name: Field name in the document front matter.
  • widget: Determines UI style and value data type (details below).
  • default (optional): Sets a default value for the field.

As described above, the widget property specifies a built-in or custom UI widget for a given field. When a content editor enters a value into a widget, that value is saved in the document front matter as the value for the name specified for that field. A full listing of available widgets can be found in the Widgets doc.

Based on this example, you can go through the post types in your site and add the appropriate settings to your Netlify CMS config.yml file. Each post type should be listed as a separate node under the collections field. See the Collections reference doc for more configuration options.

Filter

The entries for any collection can be filtered based on the value of a single field. The example collection below only shows post entries with the value en in the language field.

collections:
  - name: "posts"
    label: "Post"
    folder: "_posts"
    filter:
      field: language
      value: en
    fields:
      - {label: "Language", name: "language"}

Authentication

Now that you have your Netlify CMS files in place and configured, all that’s left is to enable authentication. We’re using the Netlify platform here because it’s one of the quickest ways to get started, but you can learn about other authentication options in the Backends doc.

Setup on Netlify

Netlify offers a built-in authentication service called Identity. In order to use it, connect your site repo with Netlify. Netlify has published a general Step-by-Step Guide for this, along with detailed guides for many popular static site generators, including Jekyll, Hugo, Hexo, Middleman, Gatsby, and more.

Enable Identity and Git Gateway

Netlify’s Identity and Git Gateway services allow you to manage CMS admin users for your site without requiring them to have an account with your Git host or commit access on your repo. From your site dashboard on Netlify:

  1. Go to Settings > Identity, and select Enable Identity service.
  2. Under Registration preferences, select Open or Invite only. In most cases, you want only invited users to access your CMS, but if you’re just experimenting, you can leave it open for convenience.
  3. If you’d like to allow one-click login with services like Google and GitHub, check the boxes next to the services you’d like to use, under External providers.
  4. Scroll down to Services > Git Gateway, and click Enable Git Gateway. This authenticates with your Git host and generates an API access token. In this case, we’re leaving the Roles field blank, which means any logged in user may access the CMS. For information on changing this, check the Netlify Identity documentation.

Add the Netlify Identity Widget

With the backend set to handle authentication, now you need a frontend interface to connect to it. The open source Netlify Identity Widget is a drop-in widget made for just this purpose. To include the widget in your site, add the following script tag in two places:

<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>

Add this to the <head> of your CMS index page at /admin/index.html, as well as the <head> of your site’s main index page. Depending on how your site generator is set up, this may mean you need to add it to the default template, or to a “partial” or “include” template. If you can find where the site stylesheet is linked, that’s probably the right place. Alternatively, you can include the script in your site using Netlify’s Script Injection feature.

When a user logs in with the Netlify Identity widget, an access token directs to the site homepage. In order to complete the login and get back to the CMS, redirect the user back to the /admin/ path. To do this, add the following script before the closing body tag of your site’s main index page:

<script>
  if (window.netlifyIdentity) {
    window.netlifyIdentity.on("init", user => {
      if (!user) {
        window.netlifyIdentity.on("login", () => {
          document.location.href = "/admin/";
        });
      }
    });
  }
</script>

Note: This example script requires modern JavaScript and does not work on IE11. For legacy browser support, use function expressions (function () {}) in place of the arrow functions (() => {}), or use a transpiler such as Babel.

Accessing the CMS

Your site CMS is now fully configured and ready for login!

If you set your registration preference to “Invite only,” invite yourself (and anyone else you choose) as a site user. To do this, select the Identity tab from your site dashboard, and then select the Invite users button. Invited users receive an email invitation with a confirmation link. Clicking the link will take you to your site with a login prompt.

If you left your site registration open, or for return visits after confirming an email invitation, access your site’s CMS at yoursite.com/admin/.

Note: No matter where you access Netlify CMS — whether running locally, in a staging environment, or in your published site — it always fetches and commits files in your hosted repository (for example, on GitHub), on the branch you configured in your Netlify CMS config.yml file. This means that content fetched in the admin UI matches the content in the repository, which may be different from your locally running site. It also means that content saved using the admin UI saves directly to the hosted repository, even if you’re running the UI locally or in staging.

Happy posting!

Intro

Overview

Netlify CMS is an open source content management system for your Git workflow that enables you to provide editors with a friendly UI and intuitive workflows. You can use it with any static site generator to create faster, more flexible web projects. Content is stored in your Git repository alongside your code for easier versioning, multi-channel publishing, and the option to handle content updates directly in Git.

At its core, Netlify CMS is an open-source React app that acts as a wrapper for the Git workflow, using the GitHub, GitLab, or Bitbucket API. This provides many advantages, including:

  • Fast, web-based UI: With rich-text editing, real-time preview, and drag-and-drop media uploads.
  • Platform agnostic: Works with most static site generators.
  • Easy installation: Add two files to your site and hook up the backend by including those files in your build process or linking to our Content Delivery Network (CDN).
  • Modern authentication: Using GitHub, GitLab, or Bitbucket and JSON web tokens.
  • Flexible content types: Specify an unlimited number of content types with custom fields.
  • Fully extensible: Create custom-styled previews, UI widgets, and editor plugins.

Netlify CMS vs. Netlify

Netlify.com is a platform you can use to automatically build, deploy, serve, and manage your frontend sites and web apps. It also provides a variety of other features like form processing, serverless functions, and split testing. Not all Netlify sites use Netlify CMS, and not all sites using Netlify CMS are on Netlify.

The folks at Netlify created Netlify CMS to fill a gap in the static site generation pipeline. There were some great proprietary headless CMS options, but no real contenders that were open source and extensible—that could turn into a community-built ecosystem like WordPress or Drupal. For that reason, Netlify CMS is made to be community-driven, and has never been locked to the Netlify platform (despite the name).

With this in mind, you can:

  • Use Netlify CMS without Netlify and deploy your site where you always have, hooking up your own CI, site hosting, CDN, etc.
  • Use Netlify without Netlify CMS and edit your static site in your code editor.
  • Or, use them together and have a fully-working CMS-enabled site with one click!

If you hook up Netlify CMS to your website, you’re basically adding a tool for content editors to make commits to your site repository without touching code or learning Git.

Find out more

  • Get a feel for the UI in the demo site. (No login required. Click the login button to go straight to the CMS editor UI.)
  • Start with a template to make a Netlify CMS-enabled site of your own.
  • Configure your existing site by following a tutorial or checking configuration options.
  • Ask questions and share ideas in the Netlify CMS community chat.
  • Get involved in new developments and become a contributor.