Setting up Netlify CMS on Hugo is fairly straight forward and involves adding couple of files into the static folder. We will begin with adding static/admin/index.html, Which doesn’t change much for any website.

<!DOCTYPE html>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Content Manager</title>
    <script src=""></script>
    <script src="^2.0.0/dist/netlify-cms.js"></script>

Loading and initializing CMS scripts will be done with Netlify snippet injection. Why add these snippets globally ? Because, user verification will redirect admin interface to home page with token. So the script must be loaded on both pages. Using snippet injection avoids messing up the carefully crafted layouts and themes.

On Netlify site settings, Go to Settings > Build & Deployment > Post processing > Snippet Injection and,

Add script to initialize CMS script before </body>

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

Add script to load CMS before </head>

<script src=""></script>


Then comes the configuration part, this part varies with how repository is set up and what information should be accessible from the admin interface. Create config.yml in static/admin directory, we’ll go through each option individually.


Netlify CMS supports multiple backends and OAuth providers. Their git-gateway backend commits directly to GitHub repos and even allow adding users who don’t have GitHub account. By default, It would be set to open registration. Change it to invitation only mode and invite yourself.

Enable Netlify Identity for the website from Settings > Identity > Services > Git Gateway.

Enable Netlify Identity

  name: git-gateway
  branch: master

Note that branch: master option, This means wherever the site is running, Whether it’s production, staging or locally, Content in admin interface will be fetched and committed to this branch. So, Be mindful about the changes you make on any environment.


This is the Killer feature for me. We discussed how the backend configuration could be dangerous and commit directly to master branch, publish_mode comes to the rescue.

publish_mode: editorial_workflow

With this single configuration, We have a three column Kanban board admin interface. Drafts, In Review and Ready with drag and drop support.

When a new post is created, It’s set to Draft status and a pull request would be created with cms/<title> as branch in the source repo. On each save, it’ll make a commit to the respective branch and if deploy previews are enabled a link to respective preview would be added to top of the post.

Later it can be moved to In Review board and then to Ready board before publishing.


As said before, this is unique for each site and heavily depends on what and how data is structured. For me, Adding posts are enough. Everything else can wait till I get to terminal.

preview_path will be used to show deploy previews links on posts.

Here is the configuration currently used by this website.

  name: git-gateway
  branch: master

publish_mode: editorial_workflow

media_folder: "static/images"
public_folder: "images"

  - name: "posts"
    label: "Posts"
    label_singular: "Post"
    folder: "content/post"
    preview_path: /{{year}}/{{slug}}
    create: true
      - { label: "Title", name: "title", widget: "string" }
      - { label: "Slug", name: "slug", widget: "string", required: false }
      - { label: "Date", name: "date", widget: "date" }
      - { label: "Tags", name: "tags", widget: list, required: false }
      - { label: "Body", name: "body", widget: "markdown" }

If you’d rather prefer to just download zip with necessary file, Here you go . Download this and unzip it to static/admin/ directory.

Feel free shoot me a mail or DM if you’ve any queries.