Unique slug validation per document type in Sanity

4 replies
Last updated: Nov 29, 2025
I'm trying to implement a unique slug validation, but I only need them unique among the same doc type (name, document._type value). The example function for this is across all documents. Does anyone have an idea how to add the type to this? (details in) 🧵
AI Update

By default, Sanity's slug field already checks for uniqueness only within documents of the same type (based on document._type). So if you're using the standard slug field without a custom isUnique function, you don't need to do anything—slugs are automatically scoped to the document type.

However, if you've implemented a custom isUnique function (like the example in the Sanity slug documentation that checks across all documents), you'll need to add the _type constraint to scope it back to the same document type.

Here's how to modify a custom isUnique function to check uniqueness only within the same document type:

// lib/isUniqueWithinType.ts
import { getPublishedId } from 'sanity';

export async function isUniqueWithinType(slug, context) {
  const { document, getClient } = context;
  const client = getClient({ apiVersion: '2025-02-19' });
  const id = document?._id;
  const type = document?._type;

  if (!id || !slug?.current || !type) {
    return true;
  }

  const publishedId = getPublishedId(id);

  const params = {
    published: publishedId,
    slug: slug.current,
    type: type, // Add the document type
  };

  // Add _type constraint to the query
  const query = groq`!defined(*[
    _type == $type &&
    !sanity::versionOf($published) &&
    slug.current == $slug
  ][0]._id)`;

  const isUnique = await client.fetch(query, params);
  return isUnique || false;
}

Then use it in your schema:

import { isUniqueWithinType } from '../lib/isUniqueWithinType';

export default {
  name: 'post',
  type: 'document',
  fields: [
    {
      name: 'slug',
      type: 'slug',
      options: {
        source: 'title',
        isUnique: isUniqueWithinType
      }
    }
  ]
}

Key changes:

  1. Extract document._type from the context
  2. Add _type == $type to the GROQ query to filter only documents of the same type
  3. Pass the type as a parameter to the query

This ensures slugs only need to be unique within documents of the same _type value (e.g., all post documents can have unique slugs, all page documents can have unique slugs, but a post and a page can share the same slug).

Show original thread
4 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.

Was this answer helpful?