This document provides a high-level overview of the Sanity Studio architecture for developers and AI agents working with this codebase.
Sanity Studio is an open-source, single-page application (SPA) for content management. It's built with React and TypeScript, designed to be highly customizable through a plugin architecture. The Studio connects to Sanity's Content Lake - a real-time, hosted data store that provides the backend infrastructure.
Key characteristics:
- React-based SPA - Modern component architecture
- Real-time collaboration - Multiple users can edit simultaneously
- Schema-driven - Content structure defined in JavaScript/TypeScript
- Highly extensible - Plugin system for customization
- GROQ-powered - Graph-Oriented Query Language for data access
sanity/
├── packages/ # All publishable and internal packages
│ ├── sanity/ # Main studio package (the "sanity" npm package)
│ ├── groq/ # GROQ language utilities
│ ├── @sanity/ # Scoped public packages
│ │ ├── types/ # TypeScript type definitions
│ │ ├── schema/ # Schema compilation and validation
│ │ ├── mutator/ # Document mutation logic
│ │ ├── diff/ # Document diffing utilities
│ │ ├── util/ # Shared utilities
│ │ └── vision/ # GROQ query tool (Studio plugin)
│ └── @repo/ # Internal monorepo tooling (not published)
│ ├── eslint-config/ # Shared ESLint configuration
│ ├── test-config/ # Shared test configuration
│ ├── tsconfig/ # Shared TypeScript configuration
│ ├── package.config/ # Build configuration utilities
│ └── ...
├── dev/ # Development studios for testing
│ ├── test-studio/ # Primary development studio
│ ├── design-studio/ # Design system testing
│ ├── studio-e2e-testing/ # E2E test fixtures
│ └── ...
├── e2e/ # End-to-end Playwright tests
├── perf/ # Performance testing
├── examples/ # Example projects
└── scripts/ # Build and maintenance scripts
The packages have a layered dependency structure. Lower-level packages have no internal dependencies, while higher-level packages compose them.
┌─────────────────┐
│ sanity │ (main studio package)
└────────┬────────┘
│
┌──────────────────────────────┼──────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ @sanity/cli │ │ @sanity/schema │ │ @sanity/vision │
└────────┬────────┘ └────────┬────────┘ └─────────────────┘
│ │ (Studio plugin)
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ @sanity/codegen │ │ @sanity/mutator │
└─────────────────┘ └────────┬────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ @sanity/types │ │ @sanity/diff │ │ @sanity/util │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ @sanity/client │ (external package - API client)
└─────────────────┘
| Package | Description |
|---|---|
sanity |
Main studio package containing UI, form builder, structure tool, and core functionality |
@sanity/types |
TypeScript type definitions for documents, schemas, and common data structures |
@sanity/schema |
Schema compilation, validation, and type inference |
@sanity/mutator |
Document mutation logic for real-time collaboration |
@sanity/diff |
Generates diffs between documents for change tracking |
@sanity/util |
Shared utilities (paths, date formatting, client helpers) |
@sanity/vision |
GROQ query playground tool (Studio plugin) |
groq |
GROQ language utilities and types |
The Studio is configured using defineConfig() which creates one or more workspaces. Each workspace represents an independent content environment with its own:
- Project ID and Dataset - Connection to Content Lake
- Schema - Document and field type definitions
- Plugins - Extended functionality
- Tools - Top-level navigation views
// sanity.config.ts
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
export default defineConfig({
name: 'default',
projectId: 'your-project-id',
dataset: 'production',
schema: {
types: [
/* document and object types */
],
},
plugins: [
structureTool(),
// Additional plugins...
],
})Key configuration files:
packages/sanity/src/core/config/types.ts- Configuration type definitionspackages/sanity/src/core/config/defineConfig.ts- Configuration factorypackages/sanity/src/core/config/resolveConfig.ts- Configuration resolution
The schema system defines the structure of content. Schemas are defined in JavaScript/TypeScript and compiled at runtime.
Schema hierarchy:
Schema
└── Types
├── Document Types (top-level content)
│ └── Fields
│ ├── Primitive (string, number, boolean, etc.)
│ ├── Complex (array, object, reference)
│ └── Special (image, file, slug, etc.)
└── Object Types (reusable field groups)
Key files:
packages/@sanity/schema/- Schema compilation and validationpackages/@sanity/types/- Schema type definitionspackages/sanity/src/core/schema/- Runtime schema utilities
The Content Lake is Sanity's hosted backend. The Studio communicates with it through:
- @sanity/client - HTTP client for CRUD operations and queries
- Real-time listeners - WebSocket connections for live updates
- Mutations - Transactional document changes
Document lifecycle:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Draft │────▶│ Published │────▶│ Historical │
│ (working) │ │ (live) │ │ (versions) │
└─────────────┘ └─────────────┘ └─────────────┘
Key stores and modules:
packages/sanity/src/core/store/- Document and data storespackages/sanity/src/core/preview/- Document preview systempackages/@sanity/mutator/- Mutation application logic
Plugins extend Studio functionality through a composable API:
import {definePlugin} from 'sanity'
export const myPlugin = definePlugin({
name: 'my-plugin',
// Add schema types
schema: {
types: [
/* custom types */
],
},
// Add tools to navigation
tools: [
/* custom tools */
],
// Customize document actions
document: {
actions: (prev, context) => [...prev, customAction],
},
// Add studio components
studio: {
components: {
/* component overrides */
},
},
})Plugin capabilities:
- Schema extensions - Add document/object types
- Tools - Add top-level navigation views
- Document actions - Publish, delete, custom actions
- Document badges - Status indicators
- Document inspectors - Side panels for document inspection
- Form components - Custom input components
- Studio components - Override navbar, layout, etc.
Tools are top-level views accessible from the Studio's main navigation. Built-in tools include:
| Tool | Package | Description |
|---|---|---|
| Structure | sanity/structure |
Document list and editing interface |
| Vision | @sanity/vision |
GROQ query playground |
| Presentation | sanity/presentation |
Visual editing preview |
Tools are React components with routing integration:
interface Tool {
name: string // URL segment
title: string // Navigation label
icon?: ComponentType // Navigation icon
component: ComponentType // Main view component
router?: Router // Tool-specific routing
canHandleIntent?: (intent, params) => boolean // Intent handling
getIntentState?: (intent, params) => state // Intent state mapping
}Key files:
packages/sanity/src/core/config/types.ts- Tool type definitionpackages/sanity/src/structure/- Structure tool implementation
Sanity supports real-time collaboration through:
- Presence - Shows which users are viewing/editing documents
- Live mutations - Changes sync across all connected clients
- Optimistic updates - UI updates immediately, syncs in background
The mutation system uses operational transformation concepts:
packages/@sanity/mutator/- Core mutation logicpackages/sanity/src/core/store/events/- Event system for changes
┌─────────────────────────────────────────────────────────────────────────┐
│ SANITY STUDIO │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Tool │ │ Form │ │ Preview │ │
│ │ Component │ │ Builder │ │ System │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └──────────────────┼──────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Document Store │◄─────── RxJS Observables │
│ └────────┬────────┘ │
│ │ │
│ ┌──────────────────┼──────────────────┐ │
│ │ │ │ │
│ ┌──────▼──────┐ ┌───────▼──────┐ ┌──────▼──────┐ │
│ │ Mutator │ │ Client │ │ Listener │ │
│ │ (patches) │ │ (queries) │ │ (real-time) │ │
│ └──────┬──────┘ └───────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
└─────────┼──────────────────┼──────────────────┼─────────────────────────┘
│ │ │
└──────────────────┼──────────────────┘
│
┌────────▼────────┐
│ Content Lake │ (Sanity's hosted backend)
│ (HTTP/WS) │
└─────────────────┘
- Component requests data via hooks (
useDocumentStore,useClient) - Document Store manages subscriptions and caching
- Client sends GROQ queries to Content Lake
- Real-time listeners push updates back
- User edits trigger form changes
- Form builder generates patches
- Mutator applies patches optimistically
- Mutations sent to Content Lake
- Confirmation/conflict resolution
| Technology | Purpose |
|---|---|
| React | UI component framework |
| TypeScript | Type safety and developer experience |
| RxJS | Reactive data streams and state management |
| Vite | Development server and build tool |
| GROQ | Query language for Content Lake |
| Portable Text | Rich text data structure |
| @sanity/ui | Design system components |
| styled-components | CSS-in-JS styling |
The main sanity package is organized into modules:
packages/sanity/src/
├── core/ # Core functionality
│ ├── config/ # Configuration system
│ ├── form/ # Form builder
│ ├── hooks/ # React hooks
│ ├── i18n/ # Internationalization
│ ├── preview/ # Document preview
│ ├── schema/ # Schema utilities
│ ├── store/ # Data stores
│ ├── studio/ # Studio shell components
│ ├── templates/ # Document templates
│ ├── validation/ # Document validation
│ └── ...
├── router/ # Client-side routing
├── structure/ # Structure tool
├── presentation/ # Presentation tool
├── desk/ # Legacy desk tool (deprecated)
└── _exports/ # Public API exports
The sanity package exposes multiple entry points:
| Import | Description |
|---|---|
sanity |
Main exports (defineConfig, components, hooks) |
sanity/structure |
Structure tool and builder |
sanity/router |
Routing utilities |
sanity/presentation |
Presentation tool |
sanity/cli |
CLI-specific exports |
sanity/_internal |
Internal APIs (unstable) |
- Official Documentation
- Plugin Development Guide
- GROQ Documentation
- Schema Configuration
- Studio Configuration
- CONTRIBUTING.md - Contribution guidelines
- AGENTS.md - AI agent guidelines for this repository