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?