Reputation: 109
Like many, all I want to do is to be able to use a simple gastby blog with NetlifyCMS. For one second I was able to get an image appear but never again after that. I've tried countless solutions from other posts and I'm just getting nowhere. Going on 3 days now.
I'm getting the common:
Field "image" must not have a selection since type "String" has no subfields
Can someone take a look and my code and see if theres something I'm missing?
config.yml
backend:
name: github
branch: development
repo: removedforworkreasons
media_folder: static/img
public_folder: /img
collections:
- name: blog
label: Blog
folder: src/posts
create: true
fields:
- { name: path, label: Path }
- { name: date, label: Date, widget: date }
- { name: title, label: Title }
- { name: description, label: Description }
- { name: image, label: Image, widget: image }
- { name: body, label: Body, widget: markdown }
gatsby-config.js
module.exports = {
siteMetadata: {
title: `removedforwork`,
description: `removedforwork`,
author: `removed`,
},
plugins: [
`gatsby-plugin-react-helmet`,
`gatsby-plugin-sass`,
`gatsby-plugin-remove-serviceworker`,
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `img`,
path: `${__dirname}/static/img`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `src`,
path: `${__dirname}/src/posts`,
},
},
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
{
resolve: `gatsby-remark-relative-images`,
options: {
// [Optional] The root of "media_folder" in your config.yml
// Defaults to "static"
staticFolderName: "static",
},
},
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 590,
},
},
],
},
},
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
},
},
{
resolve: "gatsby-plugin-react-svg",
options: {
rule: {
include: /assets/,
},
},
},
// this (optional) plugin enables Progressive Web App + Offline functionality
// To learn more, visit: https://gatsby.dev/offline
// `gatsby-plugin-offline`,
`gatsby-plugin-netlify-cms`,
`gatsby-plugin-netlify`,
],
}
gatsby-node.js (might as well throw it in)
const path = require('path')
module.exports.onCreateNode = ({ node, actions }) => {
const { createNodeField } = actions
if (node.internal.type === "MarkdownRemark") {
const slug = path.basename(node.fileAbsolutePath, '.md')
createNodeField({
node,
name: 'slug',
value: slug
})
}
}
module.exports.createPages = async ({ graphql, actions}) => {
const { createPage } = actions
const blogTemplate = path.resolve('./src/templates/blog.js')
const res = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
res.data.allMarkdownRemark.edges.forEach((edge) => {
createPage({
component: blogTemplate,
path: `/blog/${edge.node.fields.slug}`,
context: {
slug: edge.node.fields.slug
}
})
})
}
Page that displays all blog posts (Not a template) pages/blog.js
import React from "react"
import { Link, graphql, useStaticQuery } from "gatsby"
import Layout from "../components/layout/layout"
import Img from 'gatsby-image'
const Blog = () => {
const data = useStaticQuery(graphql`
query {
allMarkdownRemark {
edges {
node {
frontmatter {
title
date
image {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
fields {
slug
}
}
}
}
}
`)
return (
<>
<Layout>
<main className="main">
<div className="articles">
<h1 className="articles__title">Articles</h1>
<section className="articles__list">
{data.allMarkdownRemark.edges.map(edge => {
return (
<a className="articles__article">
<div className="articles__article-artwork">
<figure className="articles__article-artwork-wrapper">
<Img fluid={edge.node.frontmatter.image.childImageSharp.fluid} />
</figure>
</div>
<h2 className="articles__article-title">
<Link to={`/blog/${edge.node.fields.slug}`}>
{edge.node.frontmatter.title}
</Link>
</h2>
<Link>
<p>{edge.node.frontmatter.date}</p>
</Link>
<div className="articles__article-description">
<p></p>
</div>
<span className="articles__article-more">Read more...</span>
</a>
)
})}
</section>
</div>
</main>
</Layout>
</>
)
}
export default Blog
templates/blog.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout/layout"
import Img from 'gatsby-image'
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
frontmatter {
title
date
image {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
html
}
}
`
const Blog = props => {
return (
<Layout>
<main className="main">
<div className="article-page">
<header className="article-page__header">
<div className="article-page__header-inner">
<h1 className="article-page__title">
{props.data.markdownRemark.frontmatter.title}
</h1>
</div>
</header>
<Img fluid={props.data.markdownRemark.frontmatter.image.childImageSharp.fluid} />
<p>{props.data.markdownRemark.frontmatter.date}</p>
<section className="article-page">
<div className="articles-page__inner">
<div
className="article-page__content"
dangerouslySetInnerHTML={{
__html: props.data.markdownRemark.html,
}}
></div>
</div>
</section>
</div>
</main>
</Layout>
)
}
export default Blog
This has been brutal for me. I think I just need another pair of eyes to maybe point out something dumb I did, but seems like a common issues with gatsby and netlifycms.
Thanks in advance!!!
Upvotes: 4
Views: 3835
Reputation: 29320
There are multiple sources for this error:
Check the spelling of the images: if you are querying for an abc.jpg
and your image is named def.jpg
Gatsby will resolve the missing image field as a string by default. It will happen the same for missing images, as well as for wrong paths or format images types (jpg
, png
, etc).
Check plugin's order, specially for those related to the filesystem or transformers and sharps.
If your image is not a sibling, or in other words, is in the same folder as the JSON file, the appropriate plugins will resolve them to strings, as it does not actually "knows" where the file is located.
Otherwise, it will resolve the files to a file node. You can confirm this by issuing gatsby develop
, open http://localhost:8000/___graphql
, and on the right side, on the docs, go through the hierarchy of nodes. You'll see that is actually a string, but if you move the images to the same folder and make the necessary adjustments, issue gatsby clean
to purge all cached items and reissue gatsby develop
and open a new window to http://localhost:8000/___graphql
, you'll see that the now the item is actually a file node.
Resources:
Upvotes: 3
Reputation: 729
In Gatsby-config, the order of plugins does matter here:
I solved it by including gatsby-transformer-sharp
gatsby-plugin-sharp
and 'gatsby-transformer-remark' before the gatsby-source-filesystem
'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
{
resolve: 'gatsby-transformer-remark',
options: {
plugins: [
{
resolve: 'gatsby-remark-relative-images-v2',
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: 2048,
},
},
{
resolve: 'gatsby-remark-copy-linked-files',
options: {
destinationDir: 'static',
},
},
],
},
},
{
// keep as first gatsby-source-filesystem plugin for gatsby image support
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/static/assets`,
name: 'uploads',
},
},
Upvotes: 1
Reputation: 504
For anyone looking for a solution, downgrading gatsby-remark-relative-images
to version 0.3.0 worked for me:
npm i [email protected]
Don't forget to add a call to fmImagesToRelative
in onCreateNode
in gatsby-node.js
:
const {fmImagesToRelative} = require("gatsby-remark-relative-images");
// ...
exports.onCreateNode = ({node, actions, getNode}) => {
fmImagesToRelative(node); // <- this
// ...
};
Upvotes: 2