Adding custom validation to a Sanity slug field

8 replies
Last updated: Sep 14, 2022
How would I go about adding a rule in a sanity field to make sure whatever string is put into that field begins and ends with a certain character?
So for slugs, I want to make sure that when a slug is added, the user adds a beginning and trailing
and if they do not it will not allow them to save/publish until they add that.
Jul 27, 2022, 1:49 PM
user M
đź‘‹You can use
validations for that!
will make it impossible to publish unless it is full-filled in and the
validation is whatever you want the condition to be.But we have a
field ready for use, you know that?
validation: Rule =>
Jul 27, 2022, 1:57 PM
You can use the method
to check for the / in the string, and setup a conditional
if else
Jul 27, 2022, 2:00 PM
user J
! Thanks for this. I was just looking into this on the docs. I was aware of the slug field I just wanted to add a little extra customization/required-ness to it.
Jul 27, 2022, 2:03 PM
user J
I have a interesting problem.
Currently I want to use the
type: 'slug'
because of how we check for unique slug values in the options array.
However, if I have the type as slug I cannot use a custom function to check if the string starts and ends with

But if I change it to string, I cannot use the
validation method and therefore I can have multiple strings be the same.
Do you know a way I can add custom validation to slugs? Im not sure why my custom validation always errors/doesn't work with slugs unless slugs are stored differently.
Jul 27, 2022, 7:05 PM
you can use the validation for unique in a slug and add the / in your frontend…. let me check how I once did this
Jul 28, 2022, 9:57 AM
Okay here we have it:
            title: 'Slug',
            name: 'slug',
            type: 'slug',
            inputComponent: SlugInput,
            readOnly: false,
            options: {
                basePath: basePath,
                isUnique: isUniqueAcrossAllDocuments,
                source: 'title',
                maxLength: 200, // will be ignored if slugify is set
                slugify: input => input
                    .replace(/\s+/g, '-')
                    .slice(0, 200)
This is similar to the
validation and should do the trick
// /lib/isUniqueAcrossAllDocuments.js
import client from 'part:@sanity/base/client'

// Note: this assumes that every document that has a slug field
// have it on the `slug` field at the root
export function isUniqueAcrossAllDocuments(slug, options) {
    const { document } = options

    const id = document._id.replace(/^drafts\./, '')
    const params = {
        draft: `drafts.${id}`,
        published: id,

    const query = `!defined(*[!(_id in [$draft, $published]) && slug.current == $slug][0]._id)`

    return client.fetch(query, params)
A check function can be then added like the one above and set accordingly… hope that helps!
Jul 28, 2022, 10:04 AM
user J
thank you so much. I forgot to respond but I got it working as it is expected too.
Jul 29, 2022, 8:11 PM
user J
I have an additional question about the unique field.
I manipulated the function in such to make the query fetch all documents (because i want to check the slug field in all types). But in my case the
field is not global but within another type called
I created another type called
and call the unique function within this type.
when i use the query
*[slug.current == $slug || page.slug.current == $slug]
no matter what it only gives me results back from the
type but not from the `page`type. If i use the query within the vision tool it works as intended.
TL;DR why does the query from the unique field behave differently (scoped) then just in a regular use case? how can i prevent the query from being scoped?
Sep 14, 2022, 8:44 AM

Sanity– build remarkable experiences at scale

The Sanity Composable Content Cloud is the headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?