Sanity Schema Design

Master the art of defining content models with document types, field types, validation, references, arrays, and Portable Text for flexible, scalable content structures.

Schema design is the foundation of any Sanity-powered project. A well-designed schema creates an intuitive content management experience while providing the flexibility to evolve with your business needs. Sanity's approach to schemas empowers developers to model content that reflects real-world business structures rather than forcing content creators to adapt to rigid technical constraints. When combined with web development services, a solid schema foundation enables powerful content delivery across all digital channels.

This guide walks through the essential components of schema design: document types, field types, validation, references, arrays, and Portable Text--providing the knowledge you need to build scalable, maintainable content models that support your AI automation initiatives and content marketing strategies.

Understanding Document Types

Document types serve as the fundamental containers for your content in Sanity. Think of them as similar to tables in a relational database, each representing a distinct type of content in your project. A document type consists of multiple fields, maintains revision history, and can exist in different states such as published, draft, or versioned. The flexibility of document types allows you to model virtually any content structure--from blog posts and product pages to team members, locations, or custom entities specific to your business domain.

Every document type in Sanity requires a name and a type declaration, with most being declared as document type. The name serves as a unique identifier used throughout your queries and configurations, while the title provides a human-readable label shown in the Studio interface. Document types can define fields that structure the content they contain, and they automatically gain capabilities like revision tracking, draft states, and the ability to reference other documents.

schemaTypes/person.ts
1import { defineType, defineField } from 'sanity'2 3export const personType = defineType({4 name: 'person',5 title: 'Person',6 type: 'document',7 fields: [8 defineField({9 name: 'name',10 title: 'Full Name',11 type: 'string',12 }),13 defineField({14 name: 'portrait',15 title: 'Portrait',16 type: 'image',17 }),18 defineField({19 name: 'bio',20 title: 'Biography',21 type: 'text',22 }),23 defineField({24 name: 'role',25 title: 'Role',26 type: 'string',27 }),28 ],29})

Field Types Reference

Field types are the building blocks that define what kind of data each field can contain. Sanity provides a rich set of built-in field types that cover most content modeling needs, from simple text and numbers to complex structures like references and arrays.

The primitive field types handle simple, single-value data: String for short text like titles and names, Text for longer content where line breaks matter, Number for numerical values, Boolean for true/false toggles, Date and DateTime for temporal data, and URL for web addresses with built-in validation. Media types include Image for assets with hotspots and crops, and File for downloadable documents. Structural types like Object, Array, Reference, and Slug enable complex content modeling, while Geopoint handles geographical coordinates for location-based content. For advanced image handling including automatic optimization, see our Sanity Image Pipeline guide.

Field Type Categories

Sanity's field types cover all content modeling needs

Primitive Types

String, Text, Number, Boolean, Date, DateTime, URL for basic data

Media Types

Image and File types for managing assets with metadata

Structural Types

Object, Array, Reference, Slug for complex content structures

Geographic Types

Geopoint for location-based content and coordinates

Validation and Data Integrity

Validation ensures that the content entered into your Studio meets specified criteria, maintaining data quality and preventing errors. Sanity's validation system is powerful yet flexible, supporting everything from simple required field checks to complex custom validation logic that can reference other fields in the document. This is particularly important for e-commerce and pricing content where data accuracy directly impacts revenue.

Key built-in validation methods include required() for mandatory fields, min() and max() for length and value constraints, and regex() for pattern matching. For validation rules beyond these built-in methods, the custom() method allows arbitrary validation logic that receives both the field value and the document context, enabling sophisticated conditional validation based on multiple field interactions.

Field Validation Example
1defineField({2 name: 'title',3 title: 'Title',4 type: 'string',5 validation: (Rule) => Rule.required().max(100),6})7 8// Custom validation with document context9defineField({10 name: 'salePrice',11 title: 'Sale Price',12 type: 'number',13 validation: (Rule) => Rule.custom((value, context) => {14 if (value && value >= context.document?.price) {15 return 'Sale price must be less than regular price'16 }17 return true18 }),19})

References and Relationships

References create connections between documents, enabling rich content relationships without data duplication. When document A references document B, the reference stores a link to B's ID rather than copying B's content. This approach keeps data consistent--if B's content changes, all references automatically reflect the update. See our Sanity GROQ Queries guide to learn how to efficiently query across these relationships. For real-time content synchronization, explore our webhooks documentation to trigger external systems when reference data changes.

The to property specifies which document types can be referenced, allowing single or multiple type targets. By default, references prevent deletion of referenced documents to maintain data integrity. Weak references remove this protection, useful when content may be removed independently or when orphaned references are acceptable. For projects requiring references across different Sanity datasets, cross-dataset references provide advanced capabilities for content relationships spanning organizational boundaries.

Reference Field Types
1// Simple reference2defineField({3 name: 'author',4 title: 'Author',5 type: 'reference',6 to: [{ type: 'person' }],7})8 9// Multiple reference types10defineField({11 name: 'relatedContent',12 title: 'Related Content',13 type: 'reference',14 to: [15 { type: 'post' },16 { type: 'project' },17 { type: 'caseStudy' },18 ],19})20 21// Weak reference for optional relationships22defineField({23 name: 'legacyAuthor',24 title: 'Legacy Author',25 type: 'reference',26 weak: true,27 to: [{ type: 'author' }],28})

Arrays and Repeatable Content

Arrays in Sanity enable content creators to add multiple instances of a specified type. Whether it's a list of authors, a gallery of images, or a collection of testimonials, arrays provide the flexibility to handle variable-length content. Arrays become powerful when containing objects with multiple fields, enabling complex nested structures like product highlights, feature lists, or any repeatable section with consistent formatting. For multi-language content management, arrays work seamlessly with our Sanity Localization setup.

Arrays support various options including inline editing, sorting, and validation. The sortable option enables reordering, while the insertMenu configuration allows custom preview images for array items. For Sanity Studio customization, you can create custom array views that match your content modeling needs.

Array Field Types
1// Simple string array with tag layout2defineField({3 name: 'tags',4 title: 'Tags',5 type: 'array',6 of: [{ type: 'string' }],7 options: { layout: 'tags' },8})9 10// Array of objects with custom fields11defineField({12 name: 'highlights',13 title: 'Product Highlights',14 type: 'array',15 of: [16 {17 type: 'object',18 fields: [19 { name: 'icon', type: 'string', title: 'Icon' },20 { name: 'title', type: 'string', title: 'Title' },21 { name: 'description', type: 'text', title: 'Description' },22 ],23 },24 ],25})26 27// Array of references28defineField({29 name: 'relatedPosts',30 title: 'Related Posts',31 type: 'array',32 of: [{ type: 'reference', to: [{ type: 'post' }] }],33})

Portable Text: Rich Text as Structured Data

Portable Text represents rich content as an array of structured blocks rather than HTML strings. This approach provides several advantages: content renders correctly on any platform, you can customize how each block type appears, and the structure enables features like real-time collaboration without merge conflicts. Portable Text is essential for building headless CMS solutions that need to deliver consistent content across web, mobile, and other channels. Combined with Next.js integration, Portable Text enables powerful content delivery experiences.

The configuration defines block styles (normal text, headings, quotes), marks (decorators like bold and emphasis, plus annotations like links), and custom block types. Beyond text and images, Portable Text can include custom blocks like callouts, embedded content, or any specialized content type. In Next.js applications, the Portable Text component handles rendering with customizable components for each block type.

Portable Text Configuration
1defineField({2 name: 'body',3 title: 'Body',4 type: 'array',5 of: [6 {7 type: 'block',8 styles: [9 { title: 'Normal', value: 'normal' },10 { title: 'H2', value: 'h2' },11 { title: 'H3', value: 'h3' },12 { title: 'Quote', value: 'blockquote' },13 ],14 marks: {15 decorators: [16 { title: 'Strong', value: 'strong' },17 { title: 'Emphasis', value: 'em' },18 { title: 'Code', value: 'code' },19 ],20 annotations: [21 { type: 'object', name: 'link', fields: [22 { name: 'url', type: 'url' }23 ]},24 ],25 },26 },27 {28 type: 'image',29 options: { hotspot: true },30 fields: [31 { name: 'alt', type: 'string', title: 'Alt Text' },32 { name: 'caption', type: 'string', title: 'Caption' },33 ],34 },35 { type: 'code', options: { withFilename: true } },36 ],37})

Schema Organization Best Practices

As your project grows, organizing schemas into separate files improves maintainability. A well-structured project separates document types, shared objects, and reusable field definitions. This modular approach makes it easier to manage complex content models and collaborate across teams. For teams practicing SEO services, structured schema design enables powerful content workflows and search optimization.

Extract commonly used fields into their own definitions for consistency across document types. The defineType, defineField, and defineArrayMember helpers provide type safety and autocomplete support, making schema development more reliable and efficient. When your schema evolves over time, refer to our Sanity Migration guide for best practices on managing schema changes while preserving content integrity.

Frequently Asked Questions

Ready to Build with Sanity?

Explore more Sanity guides to master the complete platform, from GROQ queries to Studio customization and migration strategies.

Sources

  1. Sanity.io: Schema Documentation - Complete reference for all schema types, field properties, and validation rules
  2. Sanity.io: Introduction to Schemas - Foundational concepts for understanding schema design philosophy
  3. Sanity.io: Validation Reference - Detailed guide on validation rules and custom validation implementation
  4. Sanity.io: Portable Text - Documentation on rich text as structured data