Querying Sanity page data by slug in Gatsby without gatsby-node
Based on your question, it sounds like you're working with Gatsby pages that aren't generated through gatsby-node.js templates, and you want to dynamically query Sanity data based on each page's slug without hardcoding it.
The challenge you're facing is that Gatsby's page queries (queries using export const query) are designed to work with page context variables that are typically passed during page creation in gatsby-node.js. Since you're using Gatsby's file system routing instead of programmatic page creation, you don't have access to those context variables.
Here are your options:
Option 1: Create Pages Programmatically (Even with Different Layouts)
Even though your pages have different layouts, you can still use gatsby-node.js to create them programmatically and pass the slug as context. You can use different templates for different page types:
// gatsby-node.js
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allSanityPage {
nodes {
slug {
current
}
_id
}
}
}
`)
result.data.allSanityPage.nodes.forEach(page => {
createPage({
path: `/${page.slug.current}`,
component: require.resolve(`./src/templates/${page.slug.current}-template.js`),
context: {
slug: page.slug.current,
},
})
})
}Then in your template file, you can use the context variable:
export const query = graphql`
query($slug: String!) {
pageData: sanityPage(slug: { current: { eq: $slug } }) {
id
seoTitle
intro {
title
logo
}
}
}
`Option 2: File System Route API (Gatsby 4+) - Recommended
If you're on Gatsby 4+, you can use the File System Route API with collection routes. Create a file like src/pages/{SanityPage.slug__current}.js:
import React from 'react'
import { graphql } from 'gatsby'
export const query = graphql`
query($id: String!) {
sanityPage(id: { eq: $id }) {
id
seoTitle
intro {
title
logo
}
}
}
`
const PageTemplate = ({ data }) => {
return // your component
}
export default PageTemplateThis automatically creates pages for all your Sanity pages and provides the correct query variables. If you need different layouts, you can conditionally render components based on the slug or add a page type field in your Sanity schema.
Option 3: Use useStaticQuery and Filter
If you have a small number of pages, you could query all pages and filter in your component:
import { useStaticQuery, graphql } from 'gatsby'
const ProductPage = () => {
const data = useStaticQuery(graphql`
query {
allSanityPage {
nodes {
slug {
current
}
id
seoTitle
intro {
title
logo
}
}
}
}
`)
const pageData = data.allSanityPage.nodes.find(
page => page.slug.current === 'product'
)
return // your component
}This works but isn't ideal for performance since you're querying all pages on every page.
For your specific use case, I'd recommend Option 2 (File System Route API) if you're on Gatsby 4+, as it gives you the dynamic querying you need while keeping your pages file-based. If you need completely different layouts, you can either use conditional rendering within the template or stick with Option 1 and create pages programmatically with different template files.
Show original thread13 replies
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.