Published on

Gatsby, gatsby-image, and Netlify CMS

Last Modified on
Last modified on
Gatsby, gatsby-image, and Netlify CMS
Photo by Pawel Czerwinski on Unsplash

In my previous podcast, I talked about how I have been trying to add Netlify CMS to, my business website. Well, guess, what? I just completed implementing it a little while ago today, and everything works beautifully.

It took a few workarounds, trial and error, asking for help from the Netlfy Community (specifically and especially NetlifyCMS lead developer Shawn Erquhart, @erquhart on Twitter) and experimentation, but I finally brought it together!

The terser issue: still in the picture

The terser issue is still in the picture. Every time I make a change to my package.json, either adding or removing an npm package, I have to repeat the following steps afterwards:

rm -rf node_modules
npx npm-force-resolutions
npm i

Why? Because whenever I either add or remove a package related to Gatsby, I receive warnings that various peerDependencies are not installed, and that I have to install them myself. This behavior has been part of npm since version npm@3.

According to npmjs,

Trying to install another plugin with a conflicting requirement will cause an error. For this reason, make sure your plugin requirement is as broad as possible, and not to lock it down to specific patch versions.

Well, as you may remember if you listened to my previous podcast, I added terser 4.1.2 to my resolutions object in package.json. As I also mentioned, this took care of the source-maps issue and made sure that all packages using terser were compatible with this version which I added to my package.json. And that is why I have to repeat my npm-force-resolutions ritual every time I make Gatsby related changes to my package.json. This is also why I decided to go with using npx with the gatsby-cli, because I got so many warnings about missing peerDependencies when I tried to install it globally. So until Gatsby has resolved its dependency/peerDependency issues across the board, and more specifically the terser/source-maps issue, I will continue executing this pattern whenever I make changes to my package.json. It's a pain, but it works.

Source-maps still cause a break on build

In order to prevent a break on build due to the source-maps issue, I still have a custom webpack config added to the bottom of my gatsby-node.js file. Please refer to the post transcript of this podcast on to view the code snippet.

//turn off sourcemaps in production build no longer works
exports.onCreateWebpackConfig = ({ actions, stage }) => {
	// If production JavaScript and CSS build
	if (stage === 'build-javascript') {
		// Turn off source maps
			devtool: false,

Things did not stop there, however. I had another issue to address. That of image upload via Netlify CMS and the resulting Netlify CMS compatibility with gatsby-image and Gatsby grapql. The original structure of my website was definitely NOT compatible with Netlify CMS. Each post had its own folder. The name of the folder was the post slug, and the markdown file was named That was so that I would only have one slug to deal with and not two. Naming anything but would result in something like:

By naming the markdown file, the second post slug would be removed.

But as I said, Netlify CMS does not work with posts contained in their own individual folders containing the markdown file and any images used in the post.

I had to rename my post markdown files by replacing index with the post slug. It ended up looking something like this:

And I removed all the post folders. content/blog ended up only containing the markdown files and nothing else. I moved the images into the static folder within a subfolder called img. Then I made the necessary adjustments to the Netlify CMS config.yml related to post images, and made whatever image related adjustments needed in gatsby-config.js.

Gatsby assumes that images are in the same location as the posts. However, Netlify CMS places all images in one place. In the static folder, and then possibly in a subfolder. In my case, a subfolder called img. It is very important that you be consistent across files about the path to your blog post image(s). Double, triple check, and even quadruple check if you have to. I think that ended up being part of my problem and why I threw certain errors.

For example, at one point towards the end of my Netlify CMS journey, I was continuously getting the following error in Terminal on build:

"Field "image" must not have a selection since type "String" has no subfields."

This can be a real bug, and I found in my research that some developers used a Gatsby plugin called gatsby-remark-relative-images to fix the issue. However, in my case, I found out that it was just an inconsistency in my Netlify CMS image related paths across configuration files.

Once I made sure that all my markdown image paths were the same across configurations, static/admin/config.yml, gatsby-config.js, and all the post markdown files, everything worked as it should and resulted in a successful build locally and remotely.

Then there is the gatsby-plugin-netlify-cms-paths. Why this plugin? gatsby-plugin-netlify-cms-paths changes the file paths in your markdown files to Gatsby friendly paths when using Netlify CMS to edit them.

When this plugin is used, I can embed an image in a markdown file in markdown syntax:


and still be able to access gatsby-image's "blur-up" behavior.

Suffice it to say, I am using Netlify CMS along with npm-force-resolutions in production. It is working well thus far, and no problems on remote build. I must say that I was not familiar with the process of forcing resolutions in npm, but once I researched it further, and tested it on, I felt comfortable to use it in production. Just be sure to go through the necessary resolution steps each time you make a change to your package.json. And as I mentioned in my previous podcast,

depending on what (other) packages you are using, it might not work equally across projects.

I will be embedding this episode of Plugging in The Holes along with a transcript in the form of a post on for your hearing and reading pleasure. I will be including the related resource links mentioned in the podcast of course. Always do. Bye for now!