In 2019 I absolutely fell in love with JAMStack and static websites. My love blossomed since I've encountered Gatsby. For a lot of websites out there, there is simply no better way to do create a website. Both this website and my company's - Clean Commit - are using Gatsby with Netlify CMS.
Static websites are steadily growing as a percent of projects we work on. Having experience using Gatsby paired with Netlify CMS I found a couple tweaks that should optimize your development experience with CMS configuration.
Netlify CMS's YAML configuration can quickly become a mess
If you had the pleasure (or rather, displeasure) of working with fairly complex content in Netlify CMS you know the config.yml
file can grow quickly. One of the projects I worked on was a website for Dionysus - a company that specializes in organizing cultural events. This website contains 100s of events that are interconnected. At one point events were separated into different content types. Maintaining that CMS setup with YAML content quickly turns into a mess.
How to solve this issue? Manual Initialization!
Easy. Instead of YAML, we can use JavaScript to configure Netlify CMS with Manual Initialization. Setting up manual initialization is easy.
To enable manual initialization you need to create a JS file with the configuration and let Netlify CMS know to use it.
{
resolve: 'gatsby-plugin-netlify-cms',
options: {
manualInit: true,
modulePath: `${__dirname}/src/cms/cms.js`,
},
},
}
I strongly suggest keeping all configuration files within src/cms
to keep them well organized.
To use Netlify CMS with manual initialization, you also need to set up the general CMS settings.
import CMS from 'netlify-cms-app'
import pages from '@/cms/pages'
import posts from '@/cms/collections/posts'
window.CMS_MANUAL_INIT = true
CMS.init({
config: {
load_config_file: false,
backend: {
name: 'git-gateway',
branch: 'master',
},
media_folder: '/static/img',
public_folder: '/img',
collections: [pages, posts],
},
})
Organizing posts and pages with Netlify CMS
When using manual initialization with Netlify CMS I divide settings into 3 groups - pages (for unique pages), collections, and partials. Sometimes we need to add additional groups like settings.
Setting up pages is mostly straight-forward. The main file I use to control pages is src/cms/pages/index.js
.
import home from '@/cms/pages/home'
import blog from '@/cms/pages/blog'
import about from '@/cms/pages/about'
import privacy from '@/cms/pages/privacy'
const pages = {
name: 'pages',
label: 'Pages',
files: [home, about, blog, privacy],
}
export default pages
The main pages file is used to organize page order in the CMS and loading new pages.
import seo from '@/cms/partials/seo'
import SmallHero from '@/cms/partials/sections/small-hero'
const page = {
file: 'content/pages/home.md',
label: 'Home',
name: 'Home',
fields: [
{
label: 'Layout',
name: 'layout',
widget: 'hidden',
default: 'contact',
},
{
label: 'Type',
name: 'type',
widget: 'hidden',
default: 'page',
},
{
label: 'Title',
name: 'title',
widget: 'string',
default: '',
required: false,
},
SmallHero,
seo,
],
}
export default page
Keep Netlify CMS configuration DRY with partials
Every page file contains configuration for individual fields and uses partials to provide fields that are used across different collections/pages. The example above shows one section that is reused called SmallHero
. The second most common partial
we use is the seo
partial. This partial provides metadata information for each page and collection item.
const seo = {
label: 'SEO Settings',
name: 'seo',
widget: 'object',
collapsed: true,
fields: [
{
label: 'Title',
name: 'title',
widget: 'string',
required: false,
},
{
label: 'Meta Description',
name: 'description',
widget: 'text',
required: false,
},
{
label: 'Image',
name: 'image',
widget: 'image',
required: true,
default: '/img/shareable-default.jpg',
},
],
}
export default seo
With partials, you don't have to edit multiple files to make changes across collections or pages.
Complex data structures with Netlify CMS
I love ACF when working with WordPress. A lot of our projects since 2018 are made using Flexible Content from the Advanced Custom Fields plugin. It gives great flexibility for page creation for end users without the need for the developer's input. Headless CMSs started to adopt that feature, Prismic has Slices, Butter CMS has Components and Netlify CMS has lists.
For more on complex content solution read this article on recreating Flexible Content field with Netlify CMS & Gatsby
Lists support types
params that can enable you to create flexible content fields. I wouldn't try that without manual initialization. That old YAML file would grow enormous quickly. Not to mention moving types across different pages.
import seo from '@/cms/partials/seo'
import SmallHero from '@/cms/partials/sections/SmallHero'
import DarkSection from '@/cms/partials/sections/DarkSection'
import Perks from '@/cms/partials/sections/Perks'
import Pointers from '@/cms/partials/sections/Pointers'
import Testimonials from '@/cms/partials/sections/Testimonials'
const collection = {
name: 'services',
label: 'Services',
editor: {
preview: false,
},
description: 'Service content',
folder: 'content/services',
slug: '{{slug}}',
create: true,
fields: [
{
label: 'Type',
name: 'type',
widget: 'hidden',
default: 'service',
},
{
label: 'Layout',
name: 'layout',
widget: 'hidden',
default: 'Service',
},
{
label: 'Title',
name: 'title',
widget: 'string',
required: true,
},
{
label: 'Featured Image',
name: 'thumbnail',
widget: 'image',
required: false,
},
{
label: 'Sections',
name: 'sections',
widget: 'list',
types: [SmallHero, DarkSection, Perks, Pointers, Testimonials],
},
seo,
],
}
export default collection
The example above showcases how I created service pages on Clean Commit's website.
Here's an example section - SmallHero
const smallHero = {
label: 'Small Hero',
name: 'hero',
widget: 'object',
collapsed: false,
fields: [
{
label: 'Title',
name: 'title',
widget: 'string',
required: false,
},
{
label: 'Header',
name: 'header',
widget: 'string',
required: false,
},
{
label: 'Content',
name: 'content',
widget: 'markdown',
required: false,
},
],
}
export default smallHero
Types with Manual Initialization is a perfect match for complex website content, making it possible to use Netlify CMS on both small and medium projects efficiently. Moving configuration between projects is also a breeze.
Key takeaways for keeping Netlify CMS configuration DRY
When your project gets large, use Manual Initialization instead of YAML configuration, it's easier to maintain.
Divide your Netlify CMS configuration into 3 base groups - pages, collections, and partials. Fields shared across different entities should become partials.
For flexibility in content creation combine manual initialization with Netlify CMS types using List widget. - For more on this topic read this article on recreating Flexible Content field with Netlify CMS & Gatsby
For more helpful tips check out the Tips & Tricks category on my blog
Top comments (0)