Best practice validations for common Sanity field types

6 replies
Last updated: Nov 29, 2025
Curious if anyone has a list of “best practice” validations for different types of fields (slugs, titles, etc.)?
AI Update

Great question! While validation rules are often project-specific, there are definitely some common patterns the Sanity community has established, especially for fields like slugs.

General Validation Philosophy

As the community discussion points out, most validation is heavily dependent on your team and business needs. However, certain field types like slugs have more established web standards around them (lowercase, kebab-case formatting).

Slug Validation Best Practices

For slugs specifically, check out Simeon Griggs' excellent tutorial on Next.js and Sanity slug patterns - it's widely used in production projects.

Here's a solid slug configuration with custom slugification:

defineField({
  name: 'slug',
  title: 'Slug',
  type: 'slug',
  options: {
    source: 'title',
    slugify: input => input
      .toLowerCase()
      .replace(/\s+/g, '-')
      .replace(/[^\w\-]+/g, '')
      .replace(/\-\-+/g, '-')
      .replace(/^-+/, '')
      .replace(/-+$/, '')
      .slice(0, 200)
  },
  validation: (rule) => rule.required()
})

Common Validation Patterns by Field Type

Titles

defineField({
  name: 'title',
  title: 'Title',
  type: 'string',
  validation: (rule) => rule
    .required()
    .min(10)
    .max(100)
    .error('Title must be between 10 and 100 characters')
})

Meta Descriptions (SEO)

defineField({
  name: 'metaDescription',
  title: 'Meta Description',
  type: 'text',
  validation: (rule) => rule
    .max(160)
    .warning('Keep under 160 characters for optimal SEO')
})

Email Fields

defineField({
  name: 'email',
  type: 'string',
  validation: (rule) => rule.custom((email) => {
    if (!email) return true
    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    return regex.test(email) ? true : 'Please enter a valid email address'
  })
})

URLs

defineField({
  name: 'externalUrl',
  type: 'url',
  validation: (rule) => rule.uri({
    scheme: ['http', 'https']
  })
})

Required Fields with Context

defineField({
  name: 'publishDate',
  type: 'datetime',
  validation: (rule) => rule.custom((value, context) => {
    if (context?.document?.status === 'published' && !value) {
      return 'Publish date is required for published content'
    }
    return true
  })
})

Key Validation Features

The Sanity validation system supports three severity levels:

  • Errors: Block publishing (use .error())
  • Warnings: Allow publishing but flag issues (use .warning())
  • Info: Provide helpful context (return string from .custom())

Important Considerations

  1. Client-side only: Validation currently only runs in the Studio. If you're using the API directly, implement server-side validation separately.

  2. Title auto-generation: As mentioned in the defineField documentation, Sanity auto-generates titles from field names, but doesn't handle special cases well. Always explicitly set titles for acronyms (URL, SEO) and brand names (LinkedIn, GitHub).

  3. Descriptions matter: Use the description property to explain why validation rules exist - it helps your content team understand the requirements.

The community thread also had a creative example of prepending random hex strings to slugs for guaranteed uniqueness, though that's typically unnecessary for most use cases unless you have specific requirements around collision avoidance.

What specific field types are you working with? The validation system is quite flexible and can handle pretty much any custom logic you need!

Show original thread
6 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?