Dynamic Gatsby pages at load time with Sanity and URL parameters
Using Gatsby, I need to load in content at
load time not build time which I agree goes against the idea of Gatsby being static content but the client has dropped this on me at the final hour and I donât have much choice.
The current URL structure is like this:
<http://www.example.com/category/the-article-slug|www.example.com/category/the-article-slug>category/the-article-slug.jsâ ideally here it would somehow load
article.jsand pass it the
/category/and
/the-article-slugto fetch with the sanity client
My other option was to change the URL structure like this:
<http://www.example.com/article?category=category&slug=the-article-slug|www.example.com/article?category=category&slug=the-article-slug>I posted this on Stack Overflow but the reply I got seemed to think itâs impossible
https://stackoverflow.com/questions/66699757/dynamic-pages-at-load-time-not-build-time
I understand your predicament! You're trying to fetch Sanity content at runtime in Gatsby rather than at build time, while maintaining clean URLs like /category/the-article-slug. This is definitely possible, though it does go against Gatsby's typical static generation approach.
The matchPath Solution
The Stack Overflow response saying it's impossible is incorrect. Gatsby has a matchPath feature specifically for client-only routes that will solve your problem.
When you create your page in gatsby-node.js, specify a matchPath that matches your dynamic URL pattern:
// gatsby-node.js
exports.createPages = async ({ actions }) => {
const { createPage } = actions
createPage({
path: '/article', // The actual page component path
matchPath: '/:category/:slug', // This matches your URL pattern
component: require.resolve('./src/templates/article.js'),
})
}Accessing Parameters and Fetching Content
In your article.js template, access the route parameters and fetch from Sanity at runtime:
// src/templates/article.js
import React, { useEffect, useState } from 'react'
import sanityClient from '@sanity/client'
const client = sanityClient({
projectId: 'your-project-id',
dataset: 'production',
useCdn: false, // Use false for fresh data
apiVersion: '2023-01-01'
})
const ArticlePage = ({ location }) => {
const [content, setContent] = useState(null)
useEffect(() => {
// Extract category and slug from the URL
const pathParts = location.pathname.split('/').filter(Boolean)
const [category, slug] = pathParts
// Fetch from Sanity at load time
const query = `*[_type == "article" && category->slug.current == $category && slug.current == $slug][0]`
client.fetch(query, { category, slug })
.then(data => setContent(data))
.catch(err => console.error(err))
}, [location.pathname])
if (!content) return <div>Loading...</div>
return (
<article>
<h1>{content.title}</h1>
{/* render your content */}
</article>
)
}
export default ArticlePageHow matchPath Works
The matchPath parameter tells Gatsby: "When someone visits any URL matching /:category/:slug, serve the article.js component and let it handle the routing client-side." This is exactly what you need - clean URLs with runtime content fetching.
Important Considerations
SEO Impact: Since content loads at runtime on the client, search engines won't see the content in the initial HTML. This is a significant SEO disadvantage compared to static generation.
Performance: You'll lose the performance benefits of pre-rendered pages, as each visit requires a client-side API call to Sanity.
Alternative Approaches (if you have any flexibility):
- Gatsby DSG (Deferred Static Generation): Generate pages on first request, then cache them
- Gatsby SSR: Server-side render pages on each request with full SEO benefits
- Next.js with Sanity: Better support for dynamic content with ISR or SSR, maintaining both clean URLs and SEO
The matchPath approach will work perfectly for your /category/the-article-slug URL structure while fetching content at load time. This is a documented Gatsby feature designed exactly for client-only routes and SPA-like behavior within Gatsby sites.
Show original thread118 replies
Was this answer helpful?
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.