Issue targeting individual blog posts on portfolio site resolved with GraphQL query fix

2 replies
Last updated: Jun 18, 2022
Hello Sanity Squad. 👋
I am having some issue trying to target individual blogs post on my
portfolio site . When clicking on “First Blog”, url read correct(
…/blog/first-blog
) but content is from Second Blog.My guess would be that query in
templates/blog.js is not correct, because it is not targeting individual blogs?

//templates/blog.js

import React from 'react'
import { graphql } from 'gatsby'
import Layout from '../components/layout'
import { PortableText } from '@portabletext/react'

export const query = graphql`
  query {
    sanityPost {
      id
      slug {
        current
      }
      title
      publishedAt(formatString: "MMM Do, YYYY")
      _rawBody
    }
  }
`

const BlogPost = ({ data }) => {
  return (
    <Layout>
      <h1>{data.sanityPost.title}</h1>
      <p>{data.sanityPost.publishedAt}</p>
      <PortableText value={data.sanityPost._rawBody} />
    </Layout>
  )
}

export default BlogPost
Here is the main
pages/blog.js if needed for reference.
Lastly, my Gatsby + Sanity setup may be kind of weird because I previously was using Contentful and now migrating to Sanity.
😀My apologies for the long post and thanks in Advance!
AI Update

You're absolutely right about the issue! Your GraphQL query in templates/blog.js is not filtering by slug, so it's just returning one post (likely the first or most recent one) regardless of which URL you're on.

The fix involves two parts:

1. Update your template query to accept a slug parameter

In templates/blog.js, modify your query to filter by the slug:

export const query = graphql`
  query ($slug: String!) {
    sanityPost(slug: {current: {eq: $slug}}) {
      id
      slug {
        current
      }
      title
      publishedAt(formatString: "MMM Do, YYYY")
      _rawBody
    }
  }
`

The key changes:

  • Added query ($slug: String!) to accept a slug parameter
  • Added (slug: {current: {eq: $slug}}) to filter the specific post

2. Create pages programmatically in gatsby-node.js

You need to use Gatsby's createPages API to generate individual pages for each blog post and pass the slug as context. In your gatsby-node.js:

const path = require('path')

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  
  const result = await graphql(`
    {
      allSanityPost {
        nodes {
          slug {
            current
          }
        }
      }
    }
  `)

  result.data.allSanityPost.nodes.forEach((node) => {
    createPage({
      path: `/blog/${node.slug.current}`,
      component: path.resolve('./src/templates/blog.js'),
      context: {
        slug: node.slug.current
      }
    })
  })
}

This creates a page for each post and passes the slug as context, which becomes the $slug variable in your template query.

After making these changes, restart your Gatsby dev server (gatsby clean && gatsby develop is recommended to clear the cache).

The gatsby-source-sanity plugin handles all the data fetching from Sanity, and this pattern of using createPages with context variables is the standard Gatsby approach for dynamic pages from any CMS. The _raw fields you're using (like _rawBody) are specific to the Gatsby integration and work perfectly for rendering Portable Text content!

I was able to figure it out by parsing through sanity-gatsby-combo demo. In templates/blog.js I had to create an
$id
variable to target the id of every post.

//templates/blog.js

...
export const query = graphql`
  query($id: String!) {
    sanityPost(id: {eq: $id}){
      id
      slug {
        current
      }
      title
      publishedAt(formatString: "MMM Do, YYYY")
      _rawBody
    }
  }
`
...
Now clicking on either Second or First blog will render correct content:
https://deploy-preview-85--simonxcode.netlify.app/blog

Note to self: Learn graphQL fundamentals, variables, mutations to understand exactly what the heck is going on! 👀
Kudos for figuring it out!

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?