min read

How to configure Decap CMS (former Netlify CMS) to auto-create UUIDs for each post

Netlify CMS / Decap CMS does not come with a default UUID mechanism, although this is strongly needed if you are dealing with relations, which on the other hand is supported by it.

You could of course hand-type the ID each time, hoping it won't clash with some existing one, or you could use slugs as the ID, but often you do not have or want those kind of identifiers, nor do you want to think about random strings each time.

This is a quick solution (found on the internet) to enhance Decap CMS with a UUID widget.

In your public/admin directory...

...put the 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>
  <!-- Include the script that enables Netlify Identity on this page. -->
  <script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
</head>
<body>
<!-- Include the script that builds the page and powers Decap CMS -->
<script src="https://unpkg.com/decap-cms@^3.1.1/dist/decap-cms.js"></script>
<script src="./index.js" type="module"></script>
</body>
</html>

... put the index.js

// https://github.com/ai/nanoid
function nanoid(t = 21) {
  return crypto.getRandomValues(new Uint8Array(t))
    .reduce((t, e) => (t += (e &= 63) < 36 ? e.toString(36) : e < 62 ? (e - 26)
      .toString(36).toUpperCase() : e > 62 ? "-" : "_"), "");
}

const UuidWidget = createClass({
  componentDidMount() {
    const { value, onChange } = this.props;
    if (!value) {
      onChange(nanoid());
    }
  },

  render() {
    const { value, classNameWrapper, forID } = this.props;
    return h(
      "span",
      {
        id: forID,
        style: { fontFamily: "monospace", marginLeft: "1rem" }
        //className: classNameWrapper
      },
      value
    );
  }
});

CMS.registerWidget("uuid", UuidWidget);

...put the config.yaml and use the uuid widget

collections:
    -   name: "Posts"
        label: "Posts"
        folder: "content/blog"
        slug: "{{slug}}"
        create: true
        fields:
            - { label: "ID",
                name: "id",
                widget: "uuid"
            }
            - {
                label: "Title",
                name: "title",
                widget: "string",
                required: true
            }