Auto-generating Redirects on Slugs Change

Official(made by Sanity team)

By Jon Burbridge

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({
      type: 'sanity.function.document',
      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

Official Recipes by Sanity

First Published Timestamp Function

Featured contribution
Official(made by Sanity team)

Automatically track when content was first published with a timestamp that sets once and never overwrites, providing reliable publication history for analytics and editorial workflows.

Knut Melvær
Go to First Published Timestamp Function

Automatically tag blog posts

Featured contribution
Official(made by Sanity team)

AI-powered automatic tagging for Sanity blog posts that analyzes content to generate 3 relevant tags, maintaining consistency by reusing existing tags from your content library.

Go to Automatically tag blog posts