Codesandbox link here.
Any time I try to publish a new blog post using NetlifyCMS, it says it publishes. However my Netlify build fails and doesn't actually push any blog posts live.
Here's the error I get:
12:44:22 PM: error Your site's "gatsby-node.js" must set the page path when creating a page.
12:44:22 PM: The page object passed to createPage:
12:44:22 PM: {
12:44:22 PM: "path": null,
12:44:22 PM: "component": "/opt/build/repo/src/templates/blogTemplate.js",
12:44:22 PM: "context": {
12:44:22 PM: "slug": null
12:44:22 PM: }
12:44:22 PM: }
12:44:22 PM: See the documentation for the "createPage" action — https://www.gatsbyjs.org/docs/actions/#createPage
12:44:22 PM: not finished createPages - 0.042s
The reason why I get this error is because when new posts are published, the markdown file of the new blog post does not automatically get the 'slug' tag added. Example:
---
title: 10 of the best SEO strategies for 2021
slug: /posts/10-best-seo-strategies-2021/ <-- I had to manually add this in the markdown file. This line is completely missing when pushing new blog posts live. This is causing the site build to fail.
date: 2021-03-26T23:53:24.128Z
excerpt: >-
In this post, we go over 10 of the best SEO strategies for 2021. If you want
more business, read more now!
---
Once I manually go and add the blog post as a markdown file outside of NetlifyCMS, and add the slug tag and push up to master, it successfully builds. Obviously I don't want to do that every time, I want my site to publish normally from NetlifyCMS.
gatsby-node.js:
exports.createPages = async ({ actions, graphql, reporter }) => {
const { createPage } = actions
const blogPostTemplate = require.resolve(`./src/templates/blogTemplate.js`)
const result = await graphql(`
{
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] }
limit: 1000
) {
edges {
node {
frontmatter {
slug
}
}
}
}
}
`)
// Handle errors
if (result.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.frontmatter.slug,
component: blogPostTemplate,
context: {
// additional data can be passed via context
slug: node.frontmatter.slug,
},
})
})
}
GraphQL pageQuery in my /src/pages/posts.js file:
export const pageQuery = graphql`
query {
allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
edges {
node {
id
excerpt(pruneLength: 250)
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
}
}
}
}
}
`
Config.yml:
backend:
name: github
repo: my-repo
media_folder: uploads
public_folder: /uploads
collections:
- name: "posts"
label: "Posts"
folder: "posts"
create: true
slug: "{{slug}}"
fields:
- { label: "Title", name: "title", widget: "string" }
- { label: "Publish Date", name: "date", widget: "date" }
- { label: "Excerpt", name: "excerpt", widget: "string" }
- { label: "Body", name: "body", widget: "markdown" }
blogTemplate.js file:
export const pageQuery = graphql`
query($slug: String!) {
markdownRemark(frontmatter: { slug: { eq: $slug } }) {
html
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
excerpt
}
}
}
`
Any idea why this may be happening?
Well, you are trying to query for a
slug
field and it's never been set (at least at the beginning). Yourfrontmatter
has these fields:But not a
slug
.The standard way is to add it in your
config.yml
:Adding this, your query will work automatically.
Another method is to use the built-in listeners and the resolvers (Node APIs) from Gatsby to generate a
slug
based on a parameter previously set, but you will need to change your query. On yourgatsby-node.js
add:With
onCreateNode
you are creating a new node based on some rules (more details). That will create a new collection to be queried namedfields
with aslug
inside. So you only need to adapt it like:There's no "automated" way to achieve this without diving into more Node schemas. You are only creating a markdown file and querying its content. Which are the logic to create a
slug
from scratch?slug
fields should be always required.You can try changing the following:
To add a custom
value
based on some logic if theslug
is not defined.Another thing outside the topic. You are creating duplicated an
excerpt
:One in your markdown (coming from Netlify's CMS):
One created automatically in your GraphQL query. GraphQL + Gatsby filesystem adds a custom
excerpt
field that results from a splitting of the content of thebody
by using apruneLength
filtering outside thefrontmatter
:I think that you are mixing stuff here, I would recommend using only one of them to avoid misunderstandings in your code.