Hey, so I'm trying to get images working for blog posts for Netlify CMS. Had things working fine using regular MD with the gatsby-starter-blog but can't get it working with Netlify CMS. I think it may be something with the relative image path since it's showing up as null when it worked before but not sure. Have looked through blog posts and past issues but can't figure it out. Probably have been looking at it too long so any help would be much appreciated!
Here's the error: https://imgur.com/jhMZATJ. And here's what I have:
blog-post.js
import React from 'react'
import Img from 'gatsby-image'
import Helmet from 'react-helmet'
import { Link, graphql } from 'gatsby'
import get from 'lodash/get'
import Layout from '../components/layout'
class BlogPostTemplate extends React.Component {
render() {
const post = this.props.data.markdownRemark
const siteTitle = get(this.props, 'data.site.siteMetadata.title')
const siteDescription = post.excerpt
const { previous, next } = this.props.pageContext
return (
<Layout location={this.props.location}>
<Helmet
htmlAttributes={{ lang: 'en' }}
meta={[{ name: 'description', content: siteDescription }]}
title={`${post.frontmatter.title} | ${siteTitle}`}
/>
<Img className="mainImage" sizes={post.frontmatter.featuredImage.childImageSharp.sizes} />
<div className="site-body">
<div className="grid grid-gutters grid-justifyCenter">
<div className="grid-cell">
<div className="blogTitle singleBlog">
<h1>{post.frontmatter.title}</h1>
<h6>{post.frontmatter.date}</h6>
</div>
<div className="blogContent" dangerouslySetInnerHTML={{ __html: post.html }} />
<hr />
<ul
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-between',
listStyle: 'none',
padding: 0,
}}
>
<li>
{previous && (
<Link to={previous.fields.slug} rel="prev">
← {previous.frontmatter.title}
</Link>
)}
</li>
<li>
{next && (
<Link to={next.fields.slug} rel="next">
{next.frontmatter.title} →
</Link>
)}
</li>
</ul>
</div>
</div>
</div>
</Layout>
)
}
}
export default BlogPostTemplate
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
site {
siteMetadata {
title
author
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt
html
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
featuredImage {
childImageSharp{
sizes(maxWidth: 1500) {
...GatsbyImageSharpSizes
}
}
}
}
}
}
`
gatsby-node.js
const _ = require('lodash')
const Promise = require('bluebird')
const path = require('path')
const { createFilePath } = require('gatsby-source-filesystem')
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return new Promise((resolve, reject) => {
const blogPost = path.resolve('src/templates/blog-post.js')
resolve(
graphql(
`
{
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }, limit: 1000) {
edges {
node {
fields {
slug
}
frontmatter {
title
}
}
}
}
}
`
).then(result => {
if (result.errors) {
console.log(result.errors)
reject(result.errors)
}
// Create blog posts pages.
const posts = result.data.allMarkdownRemark.edges;
_.each(posts, (post, index) => {
const previous = index === posts.length - 1 ? null : posts[index + 1].node;
const next = index === 0 ? null : posts[index - 1].node;
createPage({
path: post.node.fields.slug,
component: blogPost,
context: {
slug: post.node.fields.slug,
previous,
next,
},
})
})
})
)
})
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
const { frontmatter } = node
if (frontmatter) {
const { image } = frontmatter
if (image) {
if (image.indexOf('/assets') === 0) {
frontmatter.image = path.relative(
path.dirname(node.fileAbsolutePath),
path.join(__dirname, '/static/', image)
)
}
}
}
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
gatsby-config.js
module.exports = {
siteMetadata: {
title: 'Test Site',
author: '',
description: '',
siteUrl: '',
},
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/src/pages`,
name: 'pages',
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/src/assets`,
name: 'images',
},
},
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
{
resolve: `gatsby-plugin-netlify-cms-paths`,
options: {
// Path to your Netlify CMS config file
cmsConfig: `/static/admin/config.yml`
}
},
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 1500,
},
},
{
resolve: `gatsby-remark-responsive-iframe`,
options: {
wrapperStyle: `margin-bottom: 1.0725rem`,
},
},
'gatsby-remark-prismjs',
'gatsby-remark-copy-linked-files',
'gatsby-remark-smartypants',
],
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-google-analytics`,
options: {
//trackingId: `ADD YOUR TRACKING ID HERE`,
},
},
`gatsby-plugin-feed`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: ``,
short_name: ``,
start_url: `/`,
background_color: `#ffffff`,
theme_color: `#141414`,
display: `minimal-ui`,
icon: `src/assets/icon.png`,
},
},
`gatsby-plugin-offline`,
`gatsby-plugin-react-helmet`,
`gatsby-plugin-netlify-cms`,
`gatsby-plugin-netlify-cms-paths`,
{
resolve: `gatsby-plugin-postcss`,
options: {
postCssPlugins: [require(`postcss-custom-properties`)({ stage: 0 })],
},
},
{
resolve: `gatsby-plugin-favicon`,
options: {
logo: "./src/assets/icon.png",
// WebApp Manifest Configuration
appName: null, // Inferred with your package.json
appDescription: null,
developerName: null,
developerURL: null,
dir: 'auto',
lang: 'en-US',
background: '#fff',
theme_color: '#fff',
display: 'standalone',
orientation: 'any',
start_url: '/',
version: '1.0',
icons: {
android: true,
appleIcon: true,
appleStartup: true,
coast: false,
favicons: true,
firefox: true,
opengraph: true,
twitter: true,
yandex: false,
windows: false
}
}
}
],
}
Netlify - config.yml
backend:
name: github
repo: jonathancary/test-site
media_folder: src/assets
public_folder: static
collections:
- name: posts
label: Posts
folder: "src/pages/posts"
create: true
fields:
- { name: title, label: Title }
- { name: path, label: Path }
- { name: date, label: Date, widget: date }
- { name: description, label: Description }
- { name: "tags", label: "Tags", widget: "list"}
- { name: "featuredImage", label: "Featured Image", widget: "image" }
- { name: body, label: Body, widget: markdown }
It's probably caused by the relative path of the images.
Instead of this:
const { frontmatter } = node
if (frontmatter) {
const { image } = frontmatter
if (image) {
if (image.indexOf('/assets') === 0) {
frontmatter.image = path.relative(
path.dirname(node.fileAbsolutePath),
path.join(__dirname, '/static/', image)
)
}
}
}
try this.
Tried that but still getting the same error. This is what the update gatsby-node.js file looks like:
const _ = require('lodash')
const Promise = require('bluebird')
const path = require('path')
const { createFilePath } = require('gatsby-source-filesystem')
const { fmImagesToRelative } = require('gatsby-remark-relative-images')
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return new Promise((resolve, reject) => {
const blogPost = path.resolve('src/templates/blog-post.js')
resolve(
graphql(
`
{
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }, limit: 1000) {
edges {
node {
fields {
slug
}
frontmatter {
title
}
}
}
}
}
`
).then(result => {
if (result.errors) {
console.log(result.errors)
reject(result.errors)
}
// Create blog posts pages.
const posts = result.data.allMarkdownRemark.edges;
_.each(posts, (post, index) => {
const previous = index === posts.length - 1 ? null : posts[index + 1].node;
const next = index === 0 ? null : posts[index - 1].node;
createPage({
path: post.node.fields.slug,
component: blogPost,
context: {
slug: post.node.fields.slug,
previous,
next,
},
})
})
})
)
})
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
fmImagesToRelative(node) // convert image paths for gatsby images
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
In my experience, the reason is that your featuredImage file are not recognized as an image File type by build process, just a normal string. So, in order to solve this, you must add the file path into source system, or check the featuredImage value, if it is right and in the assets directory.
If you had used images in assets directory, and image path is also right, then modify the gatsby-transformer-remark plugins definition in gatsby-config.js, my config is:
{
resolve: 'gatsby-transformer-remark',
options: {
"excerpt_separator": `<!-- end -->`,
plugins: [
{
resolve: 'gatsby-remark-relative-images',
options: {
name: 'uploads',
},
},
{
resolve: 'gatsby-remark-images',
options: {
// It's important to specify the maxWidth (in pixels) of
// the content container as this plugin uses this as the
// base for generating different widths of each image.
maxWidth: 1280,
},
},
{
resolve: 'gatsby-remark-copy-linked-files',
options: {
destinationDir: 'static',
}
}
]
}
},
Still didn't work, this is the build error I keep getting from Netlify after I try adding a blog post and it rebuilds:
10:50:30 PM: info bootstrap finished - 26.475 s
10:50:45 PM: success Building production JavaScript and CSS bundles — 14.255 s
10:51:09 PM: error Building static HTML failed for path "/posts/testing/"
10:51:09 PM: See our docs page on debugging HTML builds for help https://gatsby.dev/debug-html
10:51:09 PM: 21 | title={`${post.frontmatter.title} | ${siteTitle}`}
10:51:09 PM: 22 | />
10:51:09 PM: > 23 | <Img className="mainImage" sizes={post.frontmatter.featuredImage.childImageSharp.sizes} />
10:51:09 PM: | ^
10:51:09 PM: 24 | <div className="site-body">
10:51:09 PM: 25 | <div className="grid grid-gutters grid-justifyCenter">
10:51:09 PM: 26 | <div className="grid-cell">
10:51:09 PM:
10:51:09 PM: WebpackError: TypeError: Cannot read property 'childImageSharp' of null
@jonathancary can you please share a reproducible example we can have a look at?
Not sure if you were wanting me to create a public repo for it or just looking for the instructions to reproduce. Here are the steps. Let me know if you need any further details. Thanks!
Install the Gatsby Blog Starter:
gatsby new gatsby-blog https://github.com/gatsbyjs/gatsby-starter-blog
Add Netlify CMS: npm install --save netlify-cms gatsby-plugin-netlify-cms
Add it to gatsby-config.js
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
{
resolve: `gatsby-plugin-netlify-cms-paths`,
options: {
// Path to your Netlify CMS config file
cmsConfig: `/static/admin/config.yml`
}
},
backend:
name: github
repo: jonathancary/YOURREPO
media_folder: src/assets
public_folder: static
collections:
- name: posts
label: Posts
folder: "src/pages/posts"
create: true
fields:
- { name: title, label: Title }
- { name: path, label: Path }
- { name: date, label: Date, widget: date }
- { name: description, label: Description }
- { name: "tags", label: "Tags", widget: "list"}
- { name: "featuredImage", label: "Featured Image", widget: "image" }
- { name: body, label: Body, widget: markdown }
import React from 'react'
import Img from 'gatsby-image'
import Helmet from 'react-helmet'
import { Link, graphql } from 'gatsby'
import get from 'lodash/get'
class BlogPostTemplate extends React.Component {
render() {
const post = this.props.data.markdownRemark
const siteTitle = get(this.props, 'data.site.siteMetadata.title')
const siteDescription = post.excerpt
const { previous, next } = this.props.pageContext
return (
<div location={this.props.location}>
<Helmet
htmlAttributes={{ lang: 'en' }}
meta={[{ name: 'description', content: siteDescription }]}
title={`${post.frontmatter.title} | ${siteTitle}`}
/>
<Img className="mainImage" sizes={post.frontmatter.featuredImage.childImageSharp.sizes} />
<div className="site-body">
<div className="grid grid-gutters grid-justifyCenter">
<div className="grid-cell">
<div className="blogTitle singleBlog">
<h1>{post.frontmatter.title}</h1>
<h6>{post.frontmatter.date}</h6>
</div>
<div className="blogContent" dangerouslySetInnerHTML={{ __html: post.html }} />
<hr />
<ul
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-between',
listStyle: 'none',
padding: 0,
}}
>
<li>
{previous && (
<Link to={previous.fields.slug} rel="prev">
← {previous.frontmatter.title}
</Link>
)}
</li>
<li>
{next && (
<Link to={next.fields.slug} rel="next">
{next.frontmatter.title} →
</Link>
)}
</li>
</ul>
</div>
</div>
</div>
</div>
)
}
}
export default BlogPostTemplate
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
site {
siteMetadata {
title
author
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt
html
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
featuredImage {
childImageSharp{
sizes(maxWidth: 1500) {
...GatsbyImageSharpSizes
}
}
}
}
}
}
`
Commit to Github and Deploy to Netlify
Go to yourwebsite.com/admin and login in to CMS. Add a blog post with either an uploaded featured image or choosing one already in the folder. (As you can see when you choose or upload an image it doesn't show correctly in the preview panel either.
When Netlify rebuilds the site you'll get the same error and the build will fail.
@jonathancary i've picked up on your answer and i think i have a solution for your issue.
Going to break down my answer in smaller parts for a better understanding.
gatsby-config.js.static/admin/config.yml to my needs transforming it intobackend:
name: github
#name: test-repo
repo: jonniebigodes/MYREPO
media_folder: static/assets
public_folder: assets
collections:
- name: posts
label: Posts
#folder: "src/pages/posts"
folder: /content/posts
create: true
fields:
- { name: title, label: Title }
- { name: path, label: Path }
- { name: date, label: Date, widget: date }
- { name: description, label: Description }
- { name: "tags", label: "Tags", widget: "list"}
- { name: "featuredImage", label: "Featured Image", widget: "image" }
- { name: body, label: Body, widget: markdown }
content/posts/hello-world/index.md now has the following frontmatter keys inside:title: Hello World
date: "2015-05-01T22:12:03.284Z"
featuredImage: golem.jpg
tags: ["one", "zero", "one"]
path: "/posts/my-first-post"
The image was copied over a old wallpaper folder i had laying around.
gatsby-node.js so that the changes would be reflected.exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
const blogPost = path.resolve(`./src/templates/blog-post.js`)
return graphql(
`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 1000
) {
edges {
node {
id
fields {
slug
}
frontmatter {
title
path
}
}
}
}
}
`
).then(result => {
if (result.errors) {
throw result.errors
}
// Create blog posts pages.
const posts = result.data.allMarkdownRemark.edges
posts.forEach((post, index) => {
const previous = index === posts.length - 1 ? null : posts[index + 1].node
const next = index === 0 ? null : posts[index - 1].node
createPage({
//path: post.node.frontmatter.path,
path: post.node.frontmatter.path,
component: blogPost,
context: {
slug: post.node.fields.slug,
previous,
next,
},
})
})
return null
})
}
src/templates/blog-post to match yours, turning it into:import React from "react"
import { Link, graphql } from "gatsby"
import Img from "gatsby-image"
import Layout from "../components/layout"
import SEO from "../components/seo"
class BlogPostTemplate extends React.Component {
render() {
const post = this.props.data.markdownRemark
const siteTitle = this.props.data.site.siteMetadata.title
const { previous, next } = this.props.pageContext
return (
<Layout location={this.props.location} title={siteTitle}>
<SEO
title={post.frontmatter.title}
description={post.frontmatter.description || post.excerpt}
/>
<Img
className="mainImage"
fluid={post.frontmatter.featuredImage.childImageSharp.fluid}
/>
<div className="site-body">
<div className="grid grid-gutters grid-justifyCenter">
<div className="grid-cell">
<div className="blogTitle singleBlog">
<h1>{post.frontmatter.title}</h1>
<h6>{post.frontmatter.date}</h6>
</div>
<div
className="blogContent"
dangerouslySetInnerHTML={{ __html: post.html }}
/>
<hr />
<ul
style={{
display: `flex`,
flexWrap: `wrap`,
justifyContent: `space-between`,
listStyle: `none`,
padding: 0,
}}
>
<li>
{previous && (
<Link to={previous.fields.slug} rel="prev">
← {previous.frontmatter.title}
</Link>
)}
</li>
<li>
{next && (
<Link to={next.fields.slug} rel="next">
{next.frontmatter.title} →
</Link>
)}
</li>
</ul>
</div>
</div>
</div>
</Layout>
)
}
}
export default BlogPostTemplate
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
site {
siteMetadata {
title
author
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt(pruneLength: 160)
html
frontmatter {
title
date(formatString: "MMMM DD,YYYY")
featuredImage {
childImageSharp {
fluid(maxWidth: 1500) {
...GatsbyImageSharpFluid_noBase64
}
}
}
}
}
}
`
Now i would like to point out a couple of things before continuing.
query BlogPostBySlug($slug: String!) {
site {
siteMetadata {
title
author
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt
html
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
featuredImage {
childImageSharp{
sizes(maxWidth: 1500) { #<= this is deprecated
...GatsbyImageSharpSizes
}
}
}
}
}
}
The sizes part is now deprecated as of the present version of gatsby and the corresponding plugin. As you can see below;

<div location={this.props.location}>..</div>
With the above out of the way.
gatsby develop, i would get a successfull build, opening up http://localhost:8000/ would show me the following:

5:24:40 PM: error GraphQL Error Field "featuredImage" must not have a selection since type "String" has no subfields.
5:24:40 PM: file: /opt/build/repo/src/templates/blog-post.js
5:24:40 PM: 6 | author
5:24:40 PM: 7 | }
5:24:40 PM: 8 | }
5:24:40 PM: 9 | markdownRemark(fields: { slug: { eq: $slug } }) {
5:24:40 PM: 10 | id
5:24:40 PM: 11 | excerpt(pruneLength: 160)
5:24:40 PM: 12 | html
5:24:40 PM: 13 | frontmatter {
5:24:40 PM: 14 | title
5:24:40 PM: 15 | date(formatString: "MMMM DD,YYYY")
5:24:40 PM: > 16 | featuredImage {
5:24:40 PM: | ^
5:24:40 PM: 17 | childImageSharp {
5:24:40 PM: 18 | fluid(maxWidth: 1500) {
5:24:40 PM: 19 | ...GatsbyImageSharpFluid_noBase64
5:24:40 PM: 20 | }
5:24:40 PM: 21 | }
5:24:40 PM: 22 | }
5:24:40 PM: 23 | }
5:24:40 PM: 24 | }
5:24:41 PM: failed during stage 'building site': Build script returned non-zero exit code: 1
5:24:40 PM: 25 | }
I know from experience that when both the markdown and a image file are "siblings", are under the same folder when the graphql query is executed, in this case the field featuredImage is treated as a File node, instead of a string, that happens if for instance the image is one level above. Leading to this.
gatsby-remark-relative-images on npm, to see if i was missing anything. And there, under the FAQ, was the answer.gatsby-config.js to the following:module.exports = {
siteMetadata: {
title: `test_netlify_cms_image`,
author: `jonniebigodes`,
description: `Example code for netlify cms and images`,
siteUrl: `https://gatsby-starter-blog-demo.netlify.com/`,
},
plugins: [
{
resolve:`gatsby-source-filesystem`, // this entry has to be the first or will not work as per FAQ
options:{
path:`${__dirname}/static/assets`,
name:`assets`
}
},
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/content/posts`,
name: `posts`,
},
},
/* {
resolve: `gatsby-plugin-netlify-cms-paths`,
options: {
// Path to your Netlify CMS config file
cmsConfig: `/static/admin/config.yml`
}
}, */
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
`gatsby-remark-relative-images`,
/* {
resolve: `gatsby-plugin-netlify-cms-paths`,
options: {
cmsConfig: `/static/admin/config.yml`,
},
}, */
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 1500,
},
},
{
resolve: `gatsby-remark-responsive-iframe`,
options: {
wrapperStyle: `margin-bottom: 1.0725rem`,
},
},
`gatsby-remark-prismjs`,
{
resolve:`gatsby-remark-copy-linked-files`,
options:{
destinationDir:`${__dirname}/static`
}
},
{
resolve:`gatsby-remark-copy-linked-files`,
options:{
destinationDir:`${__dirname}/static`
}
},
`gatsby-remark-smartypants`,
],
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-google-analytics`,
options: {
//trackingId: `ADD YOUR TRACKING ID HERE`,
},
},
`gatsby-plugin-feed`,
/* `gatsby-plugin-offline`, */
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-plugin-typography`,
options: {
pathToConfigModule: `src/utils/typography`,
},
},
`gatsby-plugin-netlify-cms`,
`gatsby-plugin-netlify`
],
}
gatsby-node.js to the following:const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
const {fmImagesToRelative} = require('gatsby-remark-relative-images');
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
const blogPost = path.resolve(`./src/templates/blog-post.js`)
return graphql(
`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 1000
) {
edges {
node {
id
fields {
slug
}
frontmatter {
title
path
}
}
}
}
}
`
).then(result => {
if (result.errors) {
throw result.errors
}
// Create blog posts pages.
const posts = result.data.allMarkdownRemark.edges
posts.forEach((post, index) => {
// paging will not work as is, throws a build error
/* const previous = index === posts.length - 1 ? null : posts[index + 1].node
const next = index === 0 ? null : posts[index - 1].node */
createPage({
//path: post.node.frontmatter.path,
// changed to this as the first item path key processed would throw a empty string
path: post.node.frontmatter.path===""?`/posts/${post.node.fields.slug}`:post.node.frontmatter.path,
component: blogPost,
context: {
slug: post.node.fields.slug,
/* previous,
next, */
},
})
})
return null
})
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
fmImagesToRelative(node)
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
src/template\blog-post to the following:import React from "react"
import { graphql } from "gatsby"
import Img from "gatsby-image"
import Layout from "../components/layout"
import SEO from "../components/seo"
class BlogPostTemplate extends React.Component {
render() {
const post = this.props.data.markdownRemark
const siteTitle = this.props.data.site.siteMetadata.title
return (
<Layout location={this.props.location} title={siteTitle}>
<SEO
title={post.frontmatter.title}
description={post.frontmatter.description || post.excerpt}
/>
<Img
className="mainImage"
fluid={post.frontmatter.featuredImage.childImageSharp.fluid}
/>
<div className="site-body">
<div className="grid grid-gutters grid-justifyCenter">
<div className="grid-cell">
<div className="blogTitle singleBlog">
<h1>{post.frontmatter.title}</h1>
<h6>{post.frontmatter.date}</h6>
</div>
<div
className="blogContent"
dangerouslySetInnerHTML={{ __html: post.html }}
/>
<hr />
</div>
</div>
</div>
</Layout>
)
}
}
export default BlogPostTemplate
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
site {
siteMetadata {
title
author
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt(pruneLength: 160)
html
frontmatter {
title
date(formatString: "MMMM DD,YYYY")
featuredImage {
childImageSharp {
fluid(maxWidth: 1500) {
...GatsbyImageSharpFluid_noBase64
}
}
}
}
}
}
`
src/pages/index.js to the following:import React from "react"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { rhythm } from "../utils/typography"
class BlogIndex extends React.Component {
render() {
const { data } = this.props
const siteTitle = data.site.siteMetadata.title
const posts = data.allMarkdownRemark.edges
return (
<Layout location={this.props.location} title={siteTitle}>
<SEO
title="All posts"
keywords={[`blog`, `gatsby`, `javascript`, `react`]}
/>
{posts.map(({ node }) => {
const title = node.frontmatter.title || node.fields.slug
return (
<div key={node.fields.slug}>
<h3
style={{
marginBottom: rhythm(1 / 4),
}}
>
<Link style={{ boxShadow: `none` }} to={node.frontmatter.path}>
{title}
</Link>
</h3>
<small>{node.frontmatter.date}</small>
<p
dangerouslySetInnerHTML={{
__html: node.frontmatter.description || node.excerpt,
}}
/>
</div>
)
})}
</Layout>
)
}
}
export default BlogIndex
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
edges {
node {
excerpt
fields {
slug
}
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
description
path
}
}
}
}
}
`
To be sure, i went on to netlify cms and created a new post with the data as you can see below:

and

Waited for netlify to pick up on the changes and build the site once more. It went without a problem and my post was added as you can see

Before i end the comment. A couple of things.
createPage.Sorry for the extremely long comment. But it was best this way so that every step was documented in order for you to follow it and make the adjustments to your needs.
Hope it will solve your issue.
Feel free to provide feedback
Where is your netlify admin config.yml
Mine looks like this with images stored in static/img/
`backend:
name: git-gateway
repo: donaldboulton/publiuslogic
branch: master
identity_url: "https://publiuslogic.com/.netlify/identity"
gateway_url: "https://publiuslogic.com/.netlify/git"
squash_merges: true
accept_roles: #optional - accepts all users if left out
- admin
- editor
- user
display_url: https://publiuslogic.com
logo_url: https://publiuslogic.com/img/apple-touch-icon-180x180.png
publish_mode: editorial_workflow
media_folder: static/img
public_folder: /img
collections:
Go to My Gatsby Starter Publius
And use the code form there.
Most likely a error in your template or config file.
Thanks @jonniebigodes that helped solve the issue!
@jonathancary no need to thank. Glad i could be of assistance. And you managed to solve your issue
@jonniebigodes been scratching my head for hours facing this issue and your solution totally solved it. THANKS!!!!
@shanqyeet no need to thank, glad the reproduction helped you out aswell.
wow. after hours of searching this problem, I realize I had a special character in one of the image path like:
featuredimage: /img/file-with-an-é.png
I think that gatsby-remark-relative-images is having trouble with special characters in path
EDIT: I missed this component when I was cleaning up content from the starter template https://github.com/netlify-templates/gatsby-starter-netlify-cms/blob/master/src/components/PreviewCompatibleImage.js. Someone already wrote this code :)
Old comment:
I was only having issues in the Netlify CMS preview view. I finally just checked if the image was a string instead of the fluid object:
typeof image === 'string' ? (
<img src={image} alt={alt} />
) : (
<Img fluid={image.childImageSharp.fluid} alt={alt} />
)
I got the idea from https://theleakycauldronblog.com/blog/problems-with-gatsby-image-and-their-workarounds falling back to publicURL.
I'd love to find a nicer solution.
@jonniebigodes I ran into this same issue, thank you for the robust solve. However options that I'm setting for gatsby-remark-images are not being applied to said featured image. They're working on other images from the same md post, just not the frontmatter based featured image.
My config setup for the plugin:
...
{
resolve: "gatsby-transformer-remark",
options: {
plugins: [
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 1024,
backgroundColor: "#2fdf29", // for testing
quality: 100,
disableBgImageOnAlpha: true,
// trying to disable the blur effect for images I have knocked out
}
},
{
resolve: "gatsby-remark-responsive-iframe"
},
"gatsby-remark-copy-linked-files",
"gatsby-remark-autolink-headers",
"gatsby-remark-prismjs",
"gatsby-remark-check-links",
]
}
},
...
Most helpful comment
@jonathancary i've picked up on your answer and i think i have a solution for your issue.
Going to break down my answer in smaller parts for a better understanding.
gatsby-config.js.static/admin/config.ymlto my needs transforming it intocontent/posts/hello-world/index.mdnow has the following frontmatter keys inside:The image was copied over a old wallpaper folder i had laying around.
gatsby-node.jsso that the changes would be reflected.src/templates/blog-postto match yours, turning it into:Now i would like to point out a couple of things before continuing.
The sizes part is now deprecated as of the present version of gatsby and the corresponding plugin. As you can see below;

With the above out of the way.
gatsby develop, i would get a successfull build, opening uphttp://localhost:8000/would show me the following:And opening a random post would show me the following:
I know from experience that when both the markdown and a image file are "siblings", are under the same folder when the graphql query is executed, in this case the field
featuredImageis treated as aFilenode, instead of a string, that happens if for instance the image is one level above. Leading to this.gatsby-remark-relative-imageson npm, to see if i was missing anything. And there, under the FAQ, was the answer.I changed the
gatsby-config.jsto the following:gatsby-node.jsto the following:src/template\blog-postto the following:src/pages/index.jsto the following:To be sure, i went on to netlify cms and created a new post with the data as you can see below:


and
Waited for netlify to pick up on the changes and build the site once more. It went without a problem and my post was added as you can see

Before i end the comment. A couple of things.
createPage.Sorry for the extremely long comment. But it was best this way so that every step was documented in order for you to follow it and make the adjustments to your needs.
Hope it will solve your issue.
Feel free to provide feedback