Skip to main content
DISPATCH // WEB DEVELOPMENT

Sanity CMS Architecture: Schemas, GROQ Queries & Frontend Execution

An engineering guide to Sanity CMS architecture, code-first schema design, GROQ query optimization, real-time preview setups, and frontend caching.

ESTIMATED EFFORT 6 min read
VM

VISHAL MEHTA

Founder & Principal Architect, HWT TECHY

Sanity CMS Architecture: Schemas, GROQ Queries & Frontend Execution
GOOGLE STORIES HUB

Explore our full library of interactive 9:16 visual engineering and SEO stories on Google Discover.

Explore Stories ⚡
Share Article
Top Summary Answer KEY TAKEAWAYS

In-depth Sanity CMS technical guide: schema definitions, GROQ vs GraphQL, Next.js live preview, CDN caching, image asset handling, and production costs.

Introduction: The Architecture Behind Content as Data

Most content management systems force editors and developers into a specific page-building metaphor. Traditional monolithic engines store content blended directly with presentation markup. First-generation headless systems replace the template engine with a REST API, but keep rigid form fields locked inside a proprietary web interface.

Sanity CMS operates on a fundamentally different premise: content is raw structured data stored in a JSON document database called the Content Lake. The editorial client—Sanity Studio—is an open-source React application that runs locally or on your own deployment targets, giving developers total code-level control over editing interfaces, document permissions, and schema validations.

+-----------------------------------------------------------------------+
|                            EDITORIAL LAYER                            |
|  Sanity Studio (React SPA embedded or hosted independently)           |
|  - Code-first schemas (TypeScript)                                    |
|  - Custom field controls & input components                           |
|  - Real-time multiplayer synchronization (OT engine)                  |
+-----------------------------------+-----------------------------------+
                                    |
                                    | API Calls (HTTP / Event Streams)
                                    v
+-----------------------------------------------------------------------+
|                            CONTENT LAKE                               |
|  Sanity Hosted Infrastructure                                         |
|  - Real-time Document Store (JSON assets)                             |
|  - GROQ / GraphQL Query Engine                                        |
|  - Asset Pipeline (Images / Files CDN)                                |
+-----------------------------------+-----------------------------------+
                                    |
                                    | Query Responses / Webhooks
                                    v
+-----------------------------------------------------------------------+
|                            DELIVERY LAYER                             |
|  Frontend Application (Next.js, SvelteKit, Remix, Astro)              |
|  - Server-Side Rendering (SSR) & Static Generation (SSG)             |
|  - Visual Editing & Statically Invalidated Cache (ISR)                |
+-----------------------------------------------------------------------+

When implemented correctly alongside modern custom web development, Sanity enables complete decoupling between editorial workflows and rendering pipelines. However, adopting a code-first, real-time structured content platform introduces distinct architectural requirements. This guide covers how Sanity functions under the hood, how to design maintainable schemas, how to write performant queries, and how to operate Sanity in production.


Table of Contents

  1. Core Architecture: The Content Lake vs Sanity Studio
  2. Code-First Schema Design
  3. Querying Content: GROQ Deep Dive vs GraphQL
  4. Frontend Integration & Live Preview Architecture
  5. Asset Management & Image Pipeline Mechanics
  6. Caching, Edge Delivery, and Webhooks
  7. Sanity vs Traditional & Headless Competitors
  8. Frequently Asked Questions
  9. Next Steps for Engineering Teams

Core Architecture: The Content Lake vs Sanity Studio

Sanity separates administrative operations and content storage into two distinct architectural constructs:

  1. The Content Lake: Sanity's fully managed real-time database. Documents are stored as valid JSON objects. The Content Lake uses Operational Transformation (OT)—similar to Google Docs—to manage concurrent edits without locking documents or losing revision history.
  2. Sanity Studio: The administrative UI. Instead of configuring fields inside a database UI or web console, Studio schemas are declared in your application codebase using TypeScript or JavaScript. Studio is compiled as a Single Page Application (SPA) that communicates directly with the Content Lake APIs.

Document Structure and Internal Metadata

Every document saved inside the Content Lake contains system-managed fields alongside user-defined attributes:

{
  "_id": "drafts.b7a3e9c1-4560-4921-a12b-34988bc110a1",
  "_type": "article",
  "_createdAt": "2025-01-15T08:30:00Z",
  "_updatedAt": "2025-02-10T14:22:18Z",
  "_rev": "vK9xLZ8aQW1mOp3s",
  "title": "Architecting Sanity CMS for Enterprise Scale",
  "slug": {
    "_type": "slug",
    "current": "sanity-cms-architecture-guide"
  }
}

Notice the _id prefix drafts.. Sanity uses an explicit document ID naming convention to manage live and draft states:

  • drafts.b7a3...: Represents unpublished changes readable only by authenticated Studio sessions or preview tokens.
  • b7a3...: The published document accessible to public query endpoints.

Publishing a document in Sanity Studio triggers a atomic write transaction: copying the data from the drafts. ID prefix to the public document ID, then removing the draft version.


Code-First Schema Design

Defining schema models in code offers major advantages: version control via Git, automated linting, type generation, and programmatic dynamic schema generation. In Sanity Studio v3, schemas use helper functions defineType, defineField, and defineArrayMember to preserve static types throughout your project.

Production Schema Example

Below is a production-grade schema definition for a technical article document incorporating custom validation rules, references, and nested Portable Text.

// schemas/documents/article.ts
import { defineType, defineField, defineArrayMember } from 'sanity';
import { BookIcon } from '@sanity/icons';

export const articleSchema = defineType({
  name: 'article',
  title: 'Technical Article',
  type: 'document',
  icon: BookIcon,
  fields: [
    defineField({
      name: 'title',
      title: 'Article Title',
      type: 'string',
      validation: (Rule) => Rule.required().min(10).max(90),
    }),
    defineField({
      name: 'slug',
      title: 'URL Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
        isUnique: (value, context) => context.defaultIsUnique(value, context),
      },
      validation: (Rule) => Rule.required(),
    }),
    defineField({
      name: 'author',
      title: 'Author',
      type: 'reference',
      to: [{ type: 'person' }],
      validation: (Rule) => Rule.required(),
    }),
    defineField({
      name: 'coverImage',
      title: 'Cover Image',
      type: 'image',
      options: {
        hotspot: true,
      },
      fields: [
        defineField({
          name: 'alt',
          title: 'Alternative Text',
          type: 'string',
          validation: (Rule) => Rule.required().error('Alt text is mandatory for accessibility.'),
        }),
      ],
    }),
    defineField({
      name: 'body',
      title: 'Article Body',
      type: 'array',
      of: [
        defineArrayMember({
          type: 'block',
          styles: [
            { title: 'Normal', value: 'normal' },
            { title: 'H2', value: 'h2' },
            { title: 'H3', value: 'h3' },
            { title: 'Quote', value: 'blockquote' },
          ],
          lists: [
            { title: 'Bullet', value: 'bullet' },
            { title: 'Numbered', value: 'number' },
          ],
          marks: {
            decorators: [
              { title: 'Strong', value: 'strong' },
              { title: 'Emphasis', value: 'em' },
              { title: 'Code', value: 'code' },
            ],
            annotations: [
              {
                name: 'link',
                type: 'object',
                title: 'URL',
                fields: [
                  {
                    name: 'href',
                    type: 'url',
                    title: 'Target Address',
                  },
                  {
                    name: 'openInNewTab',
                    type: 'boolean',
                    title: 'Open in new tab',
                    initialValue: false,
                  },
                ],
              },
            ],
          },
        }),
        defineArrayMember({
          type: 'image',
          options: { hotspot: true },
        }),
        defineArrayMember({
          type: 'code',
          title: 'Code Block',
        }),
      ],
    }),
  ],
  preview: {
    select: {
      title: 'title',
      authorName: 'author.name',
      media: 'coverImage',
    },
    prepare(selection) {
      const { title, authorName, media } = selection;
      return {
        title,
        subtitle: authorName ? `By ${authorName}` : 'No author assigned',
        media,
      };
    },
  },
});

The Portable Text Standard

Rather than storing rich text as raw HTML strings or arbitrary Markdown, Sanity stores formatted text as an array of JSON objects structured according to the Portable Text specification.

[
  {
    "_type": "block",
    "style": "h2",
    "children": [
      {
        "_type": "span",
        "text": "Understanding Content Architecture",
        "marks": []
      }
    ]
  }
]

Storing text as clean JSON abstract syntax trees (AST) protects your frontend applications. You are never forced to use dangerous dangerouslySetInnerHTML directives. You map custom JSON block types directly to native React, Vue, or Svelte components.

If you are planning a complete platform migration or website redesign, converting HTML structures into structured Portable Text prevents markup debt from polluting your new design system.


Querying Content: GROQ Deep Dive vs GraphQL

Sanity supports GraphQL endpoints, but its primary query language is GROQ (Graph Relational Object Queries). GROQ is a declarative language designed specifically to query collections of arbitrary JSON documents without fixed schema restrictions.

GROQ Fundamentals vs SQL/GraphQL

  • Filtering: Filters operate directly inside brackets `*[_type ==
GOOGLE SEARCH CENTRAL SOURCE REPUTATION

Stay Updated via Google Preferred Sources

Add HWT Techy to your preferred sources in Google Search to receive verified updates and technical dispatches in Google Top Stories and AI Overviews.

FREE DIAGNOSTIC TOOL // INSTANT SCAN 30+ CWV CHECKS

Is Your Website Passing Core Web Vitals?

Enter your domain below to run our free, instant technical SEO audit scanner. Uncover slow LCP assets, layout shifts (CLS), and schema errors in seconds.

Need help with these strategies?

Our developer team builds custom websites, fast web apps, and Google search solutions.

Explore Services
Share Article
Start a Project