How to manage 70+ redirects from Sanity CMS instead of hardcoding in next.config.js?
Great question! Yes, you can absolutely manage redirects from Sanity instead of hardcoding 70+ entries in your next.config.js. Here's how I'd approach this:
Storing Redirects in Sanity
Create a schema for redirects in your Studio. For redirect management, string fields are the correct choice since you're storing complete URL paths, not generating slugs from other fields:
export default {
name: 'redirect',
title: 'Redirects',
type: 'document',
fields: [
{
name: 'source',
type: 'string',
title: 'Source Path',
description: 'The old URL path (e.g., /old-post-slug)',
validation: Rule => Rule.required(),
},
{
name: 'destination',
type: 'string',
title: 'Destination Path',
description: 'The new URL path (e.g., /blog/new-post-slug)',
validation: Rule => Rule.required(),
},
{
name: 'permanent',
type: 'boolean',
title: 'Permanent Redirect (301)',
description: 'Use 301 for permanent, 302 for temporary',
initialValue: true,
},
],
}Note: The slug field type is designed for generating URL-friendly identifiers from source fields (like titles) and is best used for document permalinks. For redirect management where you're storing complete path strings, regular string fields are more appropriate.
Fetching Redirects in next.config.js
In your next.config.js, fetch the redirects from Sanity at build time:
const client = require('@sanity/client')
const sanityClient = client({
projectId: 'your-project-id',
dataset: 'production',
apiVersion: '2024-01-01',
useCdn: false, // Important: always get fresh data at build time
})
module.exports = async () => {
const redirects = await sanityClient.fetch(`
*[_type == "redirect"] {
source,
destination,
permanent
}
`)
return {
async redirects() {
return redirects.map(redirect => ({
source: redirect.source,
destination: redirect.destination,
permanent: redirect.permanent ?? true,
}))
},
}
}Handling Subdomain to Path Migration
For your specific case (blog.domain.com → domain.com/blog), you can use a wildcard pattern with a has condition to handle the entire subdomain migration:
async redirects() {
// Catch-all for subdomain to new path structure
const subdomainRedirect = {
source: '/:path*',
destination: '/blog/:path*',
permanent: true,
has: [
{
type: 'host',
value: 'blog.domain.com',
},
],
}
// Individual redirects from Sanity for any custom mappings
const customRedirects = redirects.map(redirect => ({
source: redirect.source,
destination: redirect.destination,
permanent: redirect.permanent ?? true,
}))
return [subdomainRedirect, ...customRedirects]
}Important Considerations
Rebuild Requirement: Changes to next.config.js require a rebuild since redirects are evaluated at build time. When you update redirects in Sanity, you'll need to trigger a new deployment. The modern way to handle this is with Sanity Functions - you can create a function that listens for changes to redirect documents and triggers your hosting platform's build hook automatically.
Caching: Always use useCdn: false when fetching redirects at build time to ensure you get the latest data.
Alternative for Real-Time Updates: If you need redirects to update without rebuilding, you can implement them in Next.js middleware instead. The middleware fetches from Sanity on each request, but this has performance implications since it runs server-side for every navigation.
Pattern Matching Optimization: Since you're migrating from a subdomain to a path structure, you might not need all 70 individual redirects! The wildcard pattern /:path* with the has condition can handle the entire subdomain migration automatically. You'd only need individual redirect documents in Sanity for posts that also changed their slug during the migration.
This approach gives you the flexibility to manage redirects through your CMS while keeping them performant at the edge with Next.js!
Show original thread7 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.