I'm working on a website using gatsby and Netlify CMS. It's based on the gatsby-starter-netlify-cms official starter
In the starter, the images are located in the static folder. So they don't use any optimization from gatsby-remark-images.
To be compiled by gatsby-remark-images, the image in the frontmatter of a markdown needs to have a path like this:
---
image: './photo.jpg'
---
But with NetlifyCMS, the path generated looks like this and doesn't work with gatsby-remark-images (only work with an image in the static folder):
---
image: photo.jpg
---
Does anyone have been confronted with this problem?
Many thanks in advance!
Hi there !
I found this blog post about implementinggatsby-image with markdown frontmatter : https://codebushi.com/gatsby-featured-images/
You call Sharp in the GraphQL query and then pass the image into a gatsby-image Img component. I haven't implemented it yet but it seems logical.
EDIT: Oops sorry. I tried myself and i's true that you can't do anything about it. They're trying to implement a relative path for the public folder in NetlifyCMS, but in the meantime I have no idea.
Thanks for the link!
But the problem is i can't get childImageSharp on the image. It doesn't exist in the GraphQL because the path of the image in the markdown isn't relative…
I had the same problem as you @grdp. It's a relatively easy fix.
My directory structure looks like this:
gatsby-site
- content
-- news
-- img
In your gatsby-node.js
exports.onCreateNode = ({ node, getNode, boundActionCreators }) => {
const { createNodeField } = boundActionCreators;
if (node.internal.type === `MarkdownRemark`) {
fillNewsEntryData(node, createNodeField, getNode);
}
};
In a separate file (but can be done inline too):
const path = require('path');
module.exports = (node, createNodeField, getNode) => {
let banner = path.join("..", node.frontmatter.banner);
createNodeField({node, name: `banner`, value: banner})
};
As the path in the frontmatter is something like /img/uploads/fb-poszt-hatter-diploma.png adding .. before it gets us the relative path from the markdown file.
The only difference this makes is that instead of node.frontmatter.banner you'll have to use node.fields.banner
Hope this helps!
@randomchars Am I wrong to assume that this code breaks the preview in NetlifyCMS? Not when you just added the image because the image displayed is cached, but when you come back to edit the entry.
To me, it seems like to make it work completely, the only option is to put the images inside the static folder, and add the relative path to the images with your code.
That way, the image folder will be copied as is to work with NetlifyCMS, and gatsby-transformer-sharp will still detect the relative path to make it work with gatsby-image
I have been working on a custom widget to overcome NetlifyCMS's shortcoming :
https://github.com/zecakeh/react-netlifycms-custompathimage
It should work as is. And the preview should work too since it loads the images directly from the backend repository.
@zecakel great! thanks for this fix
It's working in develop mode but when i make a build, i get a webpack error:
error Building static HTML for pages failed
See our docs page on debugging HTML builds for help https://goo.gl/yL9lND
27 | message += ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.';
28 |
> 29 | var error = new Error(message);
| ^
30 | error.name = 'Invariant Violation';
31 | error.framesToPop = 1; // we don't care about reactProdInvariant's own frame
32 |
WebpackError: Minified React error #130; visit http://facebook.github.io/react/docs/error-decoder.html?invarian t=130&args[]=object&args[]= for the full message or use the non-minified dev environment for full errors and ad ditional helpful warnings.
- reactProdInvariant.js?3afb:29 reactProdInvariant
~/react-dom/lib/reactProdInvariant.js?3afb:29:1
- instantiateReactComponent.js?852a:72 instantiateReactComponent
~/react-dom/lib/instantiateReactComponent.js?852a:72:1
- ReactChildReconciler.js?dd13:42 instantiateChild
~/react-dom/lib/ReactChildReconciler.js?dd13:42:1
- traverseAllChildren.js?8c0a:75 traverseAllChildrenImpl
~/react-dom/lib/traverseAllChildren.js?8c0a:75:1
- traverseAllChildren.js?8c0a:170 traverseAllChildren
~/react-dom/lib/traverseAllChildren.js?8c0a:170:1
- ReactChildReconciler.js?dd13:72 Object.instantiateChildren
~/react-dom/lib/ReactChildReconciler.js?dd13:72:1
- ReactMultiChild.js?9682:189 ReactDOMComponent._reconcilerInstantiateChildren
~/react-dom/lib/ReactMultiChild.js?9682:189:1
- ReactMultiChild.js?9682:222 ReactDOMComponent.mountChildren
~/react-dom/lib/ReactMultiChild.js?9682:222:1
- ReactDOMComponent.js?ab8a:657 ReactDOMComponent._createContentMarkup
~/react-dom/lib/ReactDOMComponent.js?ab8a:657:1
- ReactDOMComponent.js?ab8a:524 ReactDOMComponent.mountComponent
~/react-dom/lib/ReactDOMComponent.js?ab8a:524:1
Are you sure it comes from my Widget ?
I don't have any issue when I gatsby build...
Don't you have any warnings in your console in dev mode ?
Ok it's working now! i think there was a kind of conflict with other markdown template/pages.
Now just need to fix the preview image in the netlify cms admin panel (the rawMediaPath doesn't seem to work)
Many thanks for your help and this plugin!
Or maybe i'll try to put the image folder into the static folder to solve the preview in the admin panel
Really, the rawMediaPath isn't applied ? Have you checked the preview img src attribute ? Maybe it's a mistake in the path.
rawMediaPath is working but the path with this structurehttps://raw.githubusercontent.com/user/repo/master/images/ doesn't link to an image.
Is it working the preview to you with this kind of path?
Yes it is. If you want to have the proper path just go on github.com into your repository to an image in the correct folder, then copy the url of the image and remove the filename. That's your rawMediaPath.
indeed it's working! i probably did a type-mistake in the path before.
thanks a lot!
do you have any idea how to make this image field rendering a empty string ' ' when the field is empty (not required) in the markdown? It's to avoid a Cannot read property 'childImageSharp' of null)
No I haven't looked into that yet. That's an error in React, not GraphQL, right ?
Couldn't you avoid this error by checking if the image data exists in your code first? Like this:
const image = this.props.data.markdownRemark.frontmatter.image;
if (image) {
// Do some stuff with image.childImageSharp
}
Even with a conditional like that, i have a GraphQL error (Cannot read property 'childImageSharp' of null) because in some posts there's no image ("img": null).
img {
childImageSharp {
sizes(maxWidth: 800) {
src
srcSet
}
}
}
Oh that was a mistake on my part. I always intended for it to save an empty string. I fixed it in my repository so just replace your customPathImage.js with the new one.
Thanks for the new fix but that doesn't change an empty string or a empty field. I have just tested it. Still GraphQL need a valid childImageSharp value. I have two imgfield (img1, img2), sometimes the second is not required and so empty. => Cannot read property 'childImageSharp' of null
I'll try to figure it out… but thanks a lot for the help!
main {
img1 {
childImageSharp {
sizes(maxWidth: 800) {
src
srcSet
}
}
}
img2 {
childImageSharp {
sizes(maxWidth: 800) {
src
srcSet
}
}
}
}
Does Cannot read property 'childImageSharp' of null break the build? If you have repo to reproduce this problem I will take a look.
I'm wondering if it's not better to use the body field and add images there. I just don't like the <p> and <span> created around the image in the body field.
What do you think?
Thanks @zecakeh, your custom widget worked great! I actually replaced the default image widget with that one for my deployment so I could use it for inserting images in the body too which otherwise stops working once you modify the config.yml media_folder parameter to be outside the static folder.
@grdp were you able to fix this issue? If not could you provide us with a reproduction repo? That would make it much easier to diagnose this issue.
@kakadiadarpan I solved it with this solution for gatsby v2:
https://github.com/gatsbyjs/gatsby/issues/8195#issuecomment-421745303
gatsby-node.js
const { createNodeField } = actions
const { frontmatter } = node
if (frontmatter) {
const { image } = frontmatter
if (image) {
if (image.indexOf('/img') === 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,
})
}
}
config.yml
media_folder: static/img
public_folder: /img
That's great! Thank you for the quick update. 🙂
Relative image path support is now in beta as of Netlify CMS 2.9.8-beta.2 - try it out:
npm update netlify-cms-app@beta
Then add media_folder_relative: true to your Netlify CMS config.
Have been waiting so long for it. Can't wait to test it!
@erquhart Thanks so much
@erquhart I have tried the new Nelify CMS beta but I'm getting the error: Field "image" must not have a selection since type "String" has no subfields
Here is my config.yml.
At the end of this file, I have a list widget (name: archive) with object (name: figure) and image widget in it. The error is coming from there in the GraphQL query.
backend:
name: git-gateway
branch: master
media_folder_relative: true
media_folder: static/assets
public_folder: /assets
collections:
- name: 'post'
label: 'Post'
folder: 'content/post'
create: true
slug: '{{slug}}'
fields:
- {
label: 'Template Key',
name: 'templateKey',
widget: 'hidden',
default: 'post',
}
- { label: 'Cat', name: 'cat', widget: 'hidden', default: 'total-reconstruction' }
- { label: 'Title', name: 'title', widget: 'string' }
- { label: 'Publish Date', name: 'date', widget: 'datetime' }
- { label: 'Description', name: 'description', widget: 'text' }
- { label: 'Image', name: 'image', widget: 'image' }
- { label: 'Body', name: 'body', widget: 'markdown' }
- { label: 'Tags', name: 'tags', widget: 'list' }
- {
label: 'Notes',
name: 'notes',
widget: 'list',
required: false,
fields:
[
{ label: Number, name: number, widget: string },
{ label: 'Note',
name: 'note',
widget: 'markdown'
},
],
}
- {
label: Archive,
name: archive,
widget: list,
types:
[
{ label: Figure,
name: figure,
widget: object,
fields:
[
{ label: Number, name: number, widget: string, default: '1' },
{ label: Image, name: image, widget: image },
{ label: Caption, name: caption, widget: string },
],
},
],
}
@erquhart The beta functionality kind of works, but it seems to also set relative paths on upload which messes everything up. Please check the ticket I opened in the netlify cms repo, whether this is really a bug: https://github.com/netlify/netlify-cms/issues/2696
Replied on the Netlify CMS issue 👍
Most helpful comment
I had the same problem as you @grdp. It's a relatively easy fix.
My directory structure looks like this:
In your gatsby-node.js
In a separate file (but can be done inline too):
As the path in the frontmatter is something like
/img/uploads/fb-poszt-hatter-diploma.pngadding..before it gets us the relative path from the markdown file.The only difference this makes is that instead of
node.frontmatter.banneryou'll have to usenode.fields.bannerHope this helps!