Currently, the recommended way to upload images to a static website through Netlify CMS is by using the static folder, which does not offer any support for responsiveness. I would like to ask for a way to make CMS-managed assets queryable through GraphQL.
You could setup gatsby-source-filesystem to read files from the static folder.
I think that gatsby-source-filesystem wouldn't help much here. Basically, I'm trying to read a thumbnail attribute which points to an image like /images/uploads/test.png as an absolute URL (so, the aforementioned file is physically stored at static/images/uploads/test.png). The thumbnail attribute gets read as a string instead of being transformed into an image object.
@KyleAMathews How can I transform a String node into an ImageSharp node? I just set up gatsby-source-filesystem to read files from the static folder, but need to access those images' nodes by a public path.
Basically, I have a string property called thumbnail in some of my markdown files' frontmatter, and I want to transform them into ImageSharp nodes:
E.g. from /assets/uploads/conference.jpg into an ImageSharp node with the following absolute path: C:/Development/Projects/mvk-web/static/assets/uploads/conference.jpg (where C:/Development/Projects/mvk-web is my Gatsby project root)
Use onCreateNode to create a link to the File node — can give you a code sample if that's not enough a hint.
It would be great if you could provide me a code sample. Thank you in advance!
// In your gatsby-node.js
// Not tested
exports.onCreateNode = ({ node, getNode, getNodes, boundActionCreators }) => {
const { createNode, createNodeField } = boundActionCreators
if (node.internal.type === `MarkdownRemark`) {
// Create link
// Find absolute path of linked path
const pathToFile = path.resolve(getNode(node.parent).absolutePath, node.frontmatter.thumbnail)
// Find ID of File node
const fileNode = getNodes().find(n => n.absolutePath === pathToFile)
createNodeField({
node,
name: `imageLink___NODE`,
value: fileNode.id,
})
}
// Transform the new node here and create a new node or
// create a new node field.
}
Thank you for your kind assistance! Although the createNodeField method didn't work as expected, I ended up with the following code, based on yours:
exports.onCreateNode = ({
node, getNode, getNodes, boundActionCreators,
}) => {
const { createNodeField, createParentChildLink } = boundActionCreators;
if (node.internal.type === 'MarkdownRemark') {
const slug = createFilePath({ node, getNode, basePath: 'pages' });
createNodeField({
node,
name: 'slug',
value: slug,
});
// Attach thumbnail's ImageSharp node by public path if necessary
if (typeof node.frontmatter.thumbnail === 'string') {
// Find absolute path of linked path
const pathToFile = path
.join(__dirname, 'static', node.frontmatter.thumbnail)
.split(path.sep)
.join('/');
// Find ID of File node
const fileNode = getNodes().find(n => n.absolutePath === pathToFile);
if (fileNode != null) {
// Find ImageSharp node corresponding to the File node
const imageSharpNodeId = fileNode.children.find(n => n.endsWith('>> ImageSharp'));
const imageSharpNode = getNodes().find(n => n.id === imageSharpNodeId);
// Add ImageSharp node as child
createParentChildLink({ parent: node, child: imageSharpNode });
}
}
}
};
It would be great if there was a more in-depth documentation about linking nodes (or even their properties) together.
@kripod Do you have any example of this working that I could clone and test with? I'm trying the same thing but not having much luck.
@martynhoyer Yeah, it can be found here along with a working website: https://github.com/simonyiszk/mvk-web/blob/master/gatsby-node.js
Thanks @kripod! Much appreciated. Unfortunately I'm still stuck... it seems the getNodes() call doesn't have any of the images in it so const fileNode = getNodes().find(n => n.absolutePath === pathToFile); always returns undefined. The images show in allImageSharp and allFile in GraphiQL so they seem to be getting processed correctly.
Any quick suggestions, or shall I open a new issue?
To allow using gatsby image processing plugins on your frontmatter
In each Markdown file
relpath: ../../..
logo: /static/images/myimage.png
In gatsby-config.js
Under plugins add the code to access the static image folder as files
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'static/images',
path: `${__dirname}/static/images`,
},
},
In gatsby-node.js
Create a new nodeField for each image needed
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions;
if (node.internal.type === 'MarkdownRemark') {
if (node.frontmatter.relpath && node.frontmatter.logo ) {
const logopath = node.frontmatter.relpath + node.frontmatter.logo
createNodeField({
node,
name: 'logolink',
value: logopath
});
}
}
}
In config.yml
Add media folder
media_folder: "static/images"
In each collection in config.yml
State relative path for each collection that require an image in the frontmatter as a hidden field that user doesn't need to modify
- {label: "Relative Path", name: "relpath", widget: "hidden", default: "../../.."}
Query in Graphql
{
allMarkdownRemark {
edges {
node {
id
frontmatter {
title
}
fields {
logolink {
childImageSharp {
id
}
}
}
}
}
}
}
Thank you for the tip, @waywardm!
I just came across an article about a similar situation:
https://blog.alexluong.com/generate-gatsby-image-sharp-from-an-image-url/
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions;if (node.internal.type === 'MarkdownRemark') {
if (node.frontmatter.relpath && node.frontmatter.logo ) {
const logopath = node.frontmatter.relpath + node.frontmatter.logo createNodeField({ node, name: 'logolink', value: logopath }); }}
}
@waywardm What if my frontmatter has images defined in different places? like node.frontmatter.intro.image and node.frontmatter.product.image. Is there a function that can deal with all of these cases?
Most helpful comment
Thank you for your kind assistance! Although the
createNodeFieldmethod didn't work as expected, I ended up with the following code, based on yours:It would be great if there was a more in-depth documentation about linking nodes (or even their properties) together.