What is the best way to validate that e.g. a title for a document is unique within its type?
The best way to validate that a title is unique across documents of the same type is to use a custom validation rule with Rule.custom() that queries your dataset using GROQ. This is the recommended approach rather than creating a custom input component.
Here's how to implement it:
defineField({
name: 'title',
type: 'string',
validation: (rule) =>
rule.custom(async (title, context) => {
if (!title) return true; // Allow empty values (use .required() separately if needed)
const { document, getClient } = context;
const client = getClient({ apiVersion: '2024-01-01' });
const id = document._id.replace(/^drafts\./, '');
const query = `count(*[_type == $type && title == $title && !(_id in [$id, $draftId])])`;
const params = {
type: document._type,
title,
id,
draftId: `drafts.${id}`,
};
const count = await client.fetch(query, params);
return count === 0 ? true : 'This title is already in use';
}),
})Key points about this approach:
Use
getClient()from the validation context - This gives you access to the Sanity client within your validation rule to query the dataset, as explained in the Field Validation documentation.Exclude the current document - The query filters out both the published and draft versions of the current document using
!(_id in [$id, $draftId])to avoid false positives when editing existing documents.Handle draft IDs properly - Strip the
drafts.prefix from the document ID to ensure proper comparison.Return appropriate values - Return
truefor valid values or an error message string for duplicates.
Performance consideration: Since this validation queries the dataset on every keystroke, you might want to debounce it or only run it on blur for better performance with large datasets. You can also use .warning() instead of .error() if you want to allow duplicates but warn editors about them:
validation: (rule) =>
rule.custom(async (title, context) => {
// ... same logic as above
}).warning('This title is already in use')Important note about validation scope: As mentioned in the validation documentation, validation rules currently operate client-side in the Studio only. API mutations bypass these validation rules. If you need to enforce uniqueness server-side (for API mutations or as an additional safeguard), you should implement additional checks using Sanity Functions with document-level event handlers.
This approach is simpler and more maintainable than building a custom input component, as it keeps your validation logic co-located with your schema definition where it belongs.
Show original thread5 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.