Adding Netlify CMS to Metalsmith

March 28, 2022

flexible layout flexible layout

Photo by Andrea Piacquadio from Pexels

Let's be frank, the editing experience with any Static Site Generator (SSG), for anybody who is not a developer, is teribble. As developer friendly as SSGs are, most "normal" people do not like editing content in Markdown. Many editors are used to a Wordpress-like editing experience and that's what they expect. In this post we will look at how to add the Netlify CMS to a Metalsmith website so our users will be able to enjoy non-code editing.

Netlify CMS in their own words

Static + content management = ♥

Get the speed, security, and scalability of a static site, while still providing a convenient editing interface for content.

An integrated part of your Git workflow

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.

An extensible CMS built on React

Netlify CMS is built as a single-page React app. Create custom-styled previews, UI widgets, and editor plugins or add backends to support different Git platform APIs.

Adding Netlify CMS to your Metalsmith site

There is a good, offical tutorial on their website so I'll limit this post to some observations and comments that I find noteworthy based on implementing this CMS on a Metalsmith Netlify Starter website. The Github repository for this site can be found here.

Adding local editing

According to their website, local editing is in beta. I have been using it on the Metasmith Netlify Starter website with no issues.

1 Configure the Netlify CMS proxy server port number

Create a .env file in the metalsmith root folder and define the PORT you'd like the proxy server to use. The dev server runs on http://localhost:3000.

PORT=3002

2 Add the local_backend object in config.yml

backend:
  name: git-gateway

local_backend:
  # when using a custom proxy server port
  url: http://localhost:3002/api/v1

3 Add this script to the package.json file

"edit": "cross-env NODE_ENV=development NODE_PATH=./node_modules npx netlify-cms-proxy-server & npm run watch & npm run serve"

Run npm run edit will start the local site. Navigate to http://localhost:3000/admin/ and click the login button... et voilà... the Netlify CMS.

Styling the preview pane

For the CMS to use our CSS, we'll need to register the style sheet first in the admin/index.html file.

<body>
  <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
  <script>CMS.registerPreviewStyle('https://metalsmith-netlify-cms-starter.netlify.app/assets/styles.css');</script>
</body>

Creating Custom Previews

By default the CMS shows all frontmatter fields and the content body of the page in the preview pane. For the preview to show the page as in production we have to duplicate the whole page structure in React components. This process is explained here.

As we can see in the tutorial, building the React component is done without the benefit of JSX. I am used to JSX but the browser doesn't understand it. Rather, to make this work with JSX we'd have to install Babel and convert JSX to Javascript. I'd love to use JSX but don't want to add a compile step into my front-end code.

Fortunately there is a solution, htm, with a jsx-like syntax in plain javascript. HTM looks pretty much the same as JSX, except it uses template literals. It will parse the template literals and convert them to javascript that the browser can digest.

With htm a preview page template may look like this:

// use htm so we don't have to build templates with h()
import htm from "https://unpkg.com/htm?module";
const html = htm.bind(h);

// Preview component for a Page
const Page = createClass({
  render() {
    const entry = this.props.entry;

    return html`
      <main>
        <h1>${entry.getIn(["data", "title"], null)}</h1>
        ${this.props.widgetFor("body")}
      </main>
    `;
  },
});

export default Page;

Have a look at the CMS setup for the starter to get a better idea of what this may look like.

Images

Unfortunately, Netlify CMS does not support image sub-folders. All site images will be stored in one folder. Of course Wordpress users have been doing this forever so a whole cottage industry of file manager plugins has emerged but I digress...

Yes, we'll have all images located in a single directory, for small sites this will work. For larger sites I'd recommend to use a digital asset management tool like cloudinary.com.