Custom Decap CMS previews in Gatsby
You’re using Decap CMS1 to manage the content of your Gatsby-powered website. The default Decap CMS preview displays every field, including metadata. That probably isn’t what you want.
Register a preview template
The Gatsby Decap CMS plugin allows you to customise Decap CMS using a JavaScript module. In the example below, we tell Gatsby to use our decap.js
module.
// ./gatsby-config.js
module.exports = {
plugins: [
{
resolve: 'gatsby-plugin-decap-cms',
options: {
modulePath: `${__dirname}/src/cms/decap.js`,
},
},
],
}
Our module defines a preview template for the “articles” collection and registers it with Decap CMS.
// ./src/cms/decap.js
import CMS from 'decap-cms-app'
import React from 'react'
const ArticlePreview = () => (
<article>
<h1>Custom article preview</h1>
<p>This is my new article.</p>
</article>
)
CMS.registerPreviewTemplate('articles', ArticlePreview)
Don’t repeat yourself
In reality, we probably already have an “article” component we can use. Here’s a basic example which accepts the article title and body.
// ./src/components/article.js
import React from "react"
export default function Article({ title, children }) (
<article>
<h1>{title}</h1>
{children}
</article>
)
Here is our updated preview module.
import CMS from 'decap-cms-app'
import React from 'react'
import Article from '../components/articles/article'
const ArticlePreview = () => (
<Article title="Custom article preview">
<p>This is my new article.</p>
</Article>
)
CMS.registerPreviewTemplate('articles', ArticlePreview)
Populate the preview template
The above example works, but it doesn’t do anything of value. For that, we need to retrieve the article content.
Decap CMS passes a PreviewTemplateComponentProps
object to our preview component. We’re interested in the entry
and widgetFor
properties.
The entry
property is an immutable map containing a data
key. The data
value is an immutable map containing our article fields.
Set the article title
The article title is a plain string, so we pass it directly to the Article
component.
const ArticlePreview = ({ entry }) => (
<Article title={entry.getIn(['data', 'title'])}>
<p>This is my new article.</p>
</Article>
)
Set the article body
The article body uses a Markdown widget. We need to convert the raw Markdown into HTML. That’s where the widgetFor
property comes into play.
const ArticlePreview = ({ entry, widgetFor }) => (
<Article title={entry.getIn(['data', 'title'])}>
<section dangerouslySetInnerHTML={{ __html: widgetFor('body') }} />
</Article>
)
Footnotes
Sign up for my newsletter
A monthly round-up of blog posts, projects, and internet oddments.