Auto-generating Redirects on Slugs Change
A Sanity function that tracks slug changes and creates redirects automatically.
schemaTypes/redirect.ts
import {defineType, defineField, type Rule, type Slug} from 'sanity'
// Shared validation for our redirect slugs
const slugValidator = (rule: Rule) =>
rule.required().custom((value: Slug) => {
if (!value || !value.current) return "Can't be blank"
if (!value.current.startsWith('/')) {
return 'The path must start with a /'
}
return true
})
export const redirectType = defineType({
name: 'redirect',
title: 'Redirect',
type: 'document',
description: 'Redirect for next.config.js',
fields: [
defineField({
name: 'source',
type: 'slug',
validation: (rule: Rule) => slugValidator(rule),
}),
defineField({
name: 'destination',
type: 'slug',
validation: (rule: Rule) => slugValidator(rule),
}),
defineField({
name: 'permanent',
type: 'boolean',
}),
],
// null / false makes it temporary (307)
initialValue: {
permanent: true,
},
})index.ts
import {createClient} from '@sanity/client'
import {documentEventHandler} from '@sanity/functions'
export const handler = documentEventHandler(async ({context, event}) => {
const client = createClient({
...context.clientOptions,
useCdn: false,
apiVersion: '2025-05-08',
})
const {beforeSlug, slug} = event.data
if (!slug || !beforeSlug) {
console.log('No slug or beforeSlug')
return
}
if (slug === beforeSlug) {
console.log('Slug did not change')
return
}
// check if redirect already exists
const existingRedirect = await client.fetch(
`*[_type == "redirect" && source.current == "${beforeSlug}"][0]`,
)
if (existingRedirect) {
console.log(`Redirect already exists for source ${beforeSlug}`)
return
}
// check for loops
const loopRedirect = await client.fetch(
`*[_type == "redirect" && source.current == "${slug}" && destination.current == "${beforeSlug}"][0]`,
)
if (loopRedirect) {
console.log('Redirect loop detected')
return
}
const redirect = {
_type: 'redirect',
source: {
current: beforeSlug,
},
destination: {
current: slug,
},
permanent: true,
}
try {
const res = await client.create(redirect)
console.log(`🔗 Redirect from ${beforeSlug} to ${slug} was created ${JSON.stringify(res)}`)
} catch (error) {
console.log(error)
}
})sanity.blueprint.ts
import {defineBlueprint, defineDocumentFunction} from '@sanity/blueprints'
export default defineBlueprint({
resources: [
defineDocumentFunction({
name: 'auto-redirect',
src: './functions/auto-redirect',
memory: 2,
timeout: 30,
event: {
on: ['publish'],
filter: 'delta::changedAny(slug.current)',
projection: '{"beforeSlug": before().slug.current, "slug": after().slug.current}',
},
}),
],
})The Problem: Managing URL redirects manually becomes a maintenance nightmare as your site grows. When content editors change slugs, move pages, or restructure your site, you need redirects to preserve SEO rankings and prevent broken links. Without automation, you're stuck maintaining redirect lists in multiple places, risking inconsistencies and errors.
The Solution: This function automatically creates and manages redirects when document slugs change in Sanity. It watches for slug modifications and ensures proper redirect handling - all without manual intervention.
Quick Start
View full instructions and source code at github.com/sanity-io/sanity/tree/main/examples/functions/auto-redirect
Initialize blueprints if you haven't already:
npx sanity blueprints init
Add the function to your project:
npx sanity blueprints add function --example auto-redirect
Deploy to production:
npx sanity blueprints deploy
How It Works
When a document's slug field changes, the function automatically:
- Triggers when documents are updated if the `slug` field was changed
- Creates appropriate redirect records
- Makes redirects available for your frontend to query
Key Benefits
- Zero maintenance redirects - No more manual redirect management
- SEO preservation - Automatically maintains link equity when URLs change
- Instant updates - Redirects are created the moment a slug changes
- Framework agnostic - Works with any frontend framework. Read more below.
Technical Implementation
The function uses Sanity's event-driven architecture to monitor document changes. It's built with:
- Event triggers on document update events
- GROQ filtering to detect slug field changes
- Automatic redirect document creation
Perfect For
- Content teams who frequently update and restructure content
- SEO-focused sites where broken links mean lost rankings
- Large editorial sites with hundreds of pages and frequent URL changes
Frontend Implementation
Every frontend framework handles redirects differently - some use configuration files, others use middleware, and the specifics vary widely. The auto-redirect function creates the redirect documents in Sanity, but you'll need to implement how your frontend consumes them.
For detailed guidance on implementing redirects with your specific framework (Next.js, Nuxt, Remix, Astro, etc.), check out the comprehensive Managing Redirects with Sanity guide. This guide covers:
- How different frameworks handle redirect precedence
- Server-side vs client-side redirect strategies
- Framework-specific code examples and patterns
- Handling splat/dynamic route redirects
- Best practices for redirect management at scale
For complete implementation details and the function source code, visit the GitHub repository.
Contributor
Jon Burbridge
Senior Solution Architect at Sanity.io