Stack Innovations / Services / CMS / Sanity
CMS / 10 — Sanity · schema-as-code · Portable Text · GROQ

Sanity, with the Studio actually customized.

Most Sanity projects ship a beautiful API and the default Studio. We treat Sanity as code — schema.ts, sanity.config.ts, custom desk structures, custom inputs, real-time collaboration tuned for your editors. Headless content with a head your team will fight to use.

01 — In numbers

Five years shipping
schemas at scale.

Each stat is a field. Hover any to see how it'd be defined in schema.ts — counters scrub with scroll because there's no other reason to lie about a number.

number studiosShipped
0+ Sanity Studios shipped
defineField({
  name: 'studiosShipped',
  type: 'number',
  validation: Rule => Rule.min(40),
})
number documentsModeled
0+ Documents modeled · live
defineField({
  name: 'documentsModeled',
  type: 'number',
  validation: Rule => Rule.required(),
})
number customStudioApps
0+ Custom Studio inputs & tools
defineField({
  name: 'customStudioApps',
  type: 'number',
  options: { layout: 'numbered' },
})
number defaultStudios
0 Default Studios shipped
defineField({
  name: 'defaultStudios',
  type: 'number',
  initialValue: 0,
})
02 — What we build

A full-stack Sanity practice.

Click the desk on the left — the open document changes. Each capability is treated as a real Studio document with structured fields.

Stack · Sanity Studio desk › capability › studio-customization 3 online
capability _id: cap-studio-01 published

Studio customization, built around your team.

type: capability updated: 09:42 today by: stack-eng
title · Symbol

Studio customization, built around your team.

summary · Text

Custom desk structure, custom inputs (color picker, geo, marketplace lookup), structure builder for editor flows, and tools (SEO score, AI summary, channel preview) added to the sidebar.

items · Array of String
  • Custom desk structures & document panes
  • Custom inputs · React components
  • Sidebar tools · SEO, AI, preview
  • Studio extensions & plugins
  • Theme customization · brand-aligned
capability _id: cap-schema-01 published

Schema-as-code, versioned and reviewed.

type: capability updated: yesterday by: stack-eng
summary · Text

Schemas live in TypeScript, version-controlled, code-reviewed, deployed via the same pipeline as the rest of your code. References, conditional fields, validations, custom types — typed end-to-end.

items · Array of String
  • TypeScript schemas · defineType()
  • References, multi-refs, conditional fields
  • Validation rules · Rule.required()
  • Custom types · reusable across projects
  • Schema migrations · reversible
capability _id: cap-portable-01 published

Portable Text, structured down to the prose.

type: capability updated: 2d ago by: stack-eng
summary · Text

Rich text isn't HTML soup — it's structured JSON blocks. We design custom block types (callouts, quotes, embeds), custom inline marks, and renderers that hold up across web, mobile, email, voice.

items · Array of String
  • Custom Portable Text blocks
  • Inline marks & annotations
  • Renderers per surface (React, RN, email)
  • Editor extensions · @mentions, slash menus
capability _id: cap-groq-01 published

GROQ & APIs, shaped to the screen.

type: capability updated: 4d ago by: stack-eng
summary · Text

GROQ is the API. We model queries that fetch exactly what each surface needs — projections, references resolved, dereferenced assets, paginated lists. Cached at the edge with on-demand revalidation.

items · Array of String
  • GROQ projections & joins
  • GraphQL fallback when needed
  • Edge caching · webhooks · ISR
  • Live queries · client.observable
capability _id: cap-presence-01 published

Realtime & presence, tuned for editors.

type: capability updated: 1w ago by: stack-eng
summary · Text

Sanity ships realtime collaboration. We tune presence indicators, lock conflicts, draft handoff, and per-document chat — so two editors working on the same article actually feels like a Google Doc, not a war.

items · Array of String
  • Presence cursors & avatars
  • Conflict resolution · field-level
  • Draft · review · publish workflow
  • Per-document comments
capability _id: cap-migrate-01 published

Migrations, schema-aware and reversible.

type: capability updated: 2w ago by: stack-eng
summary · Text

From WordPress, Drupal, Contentful, Strapi, or that homegrown CMS no one wants to touch. We model the schema first, write migrations as reversible scripts, run them against a staging dataset, and cut over with redirects mapped.

items · Array of String
  • Schema-first migration design
  • Staging datasets · dry runs
  • Reversible scripts · safe rollback
  • 301s, sitemaps, SEO continuity
03 — Schema-as-code → Studio

Edit the schema.
The Studio follows.

This is what makes Sanity itself: schemas are TypeScript files. Click any line to toggle that field's behavior — the Studio on the right re-renders. No CMS GUI, no clicks-through-twelve-screens. Code → UI, in real time.

schema.ts sanity.config.ts desk.ts
live HMR


      
Click any toggleable line in the schema to flip it. Watch the Studio redraw.
Studio · preview Draft
type · article _id: drafts.spring-issue
Keep it under 60 characters for SEO.
/articles/
H1H2B|"</>· list↪ img

block · h2 Six things, made slow.

block · paragraph Linen, oak, oxidized brass — six considered pieces this season. Mailed from Casper.

block · imageCard spring-cover.jpg · 2400×1600

Iris Halberg linked · published
essay catalogue spring 2026 + add
draft · auto-save Publish →
04 — Why us

Stack Innovations vs the typical Sanity build.

Same platform, two schema.ts files. The diff tells the story.

typical/schema.ts — typical Sanity build
import {defineType} from 'sanity'

export const article = defineType({
  name: 'article',
  type: 'document',
  fields: [
    {name: 'title',  type: 'string'},
    {name: 'body',   type: 'string'},
    {name: 'author', type: 'string'},
    {name: 'date',   type: 'string'},
  ],
})

// no validations
// no references
// no portable text
// no custom inputs
// just strings, everywhere.
stack/schema.ts — Stack Innovations
import {defineType, defineField} from 'sanity'
import {portableText} from './blocks'
import {seoFields} from './seo'

export const article = defineType({
  name: 'article',
  type: 'document',
  fields: [
    defineField({name: 'title',  type: 'string',
      validation: R => R.required().max(60)}),
    defineField({name: 'slug',   type: 'slug',
      options: {source: 'title'}}),
    defineField({name: 'body',   type: portableText}),
    defineField({name: 'author', type: 'reference',
      to: [{type: 'person'}]}),
    defineField({name: 'cover',  type: 'imageCard'}),
    defineField({name: 'tags',   type: 'array',
      of: [{type: 'reference', to: [{type: 'tag'}]}]}),
    ...seoFields,
  ],
  preview: {select: {title: 'title', media: 'cover'}},
})
typical · flat strings Stack · validated, referenced, structured
05 — Realtime collaboration

Three editors.
One document.

Sanity's real-time engine is its quietest superpower. Here's a document being edited by three avatars at once — cursors, field locks, presence pills, edit notifications. This is what your team gets.

type · article
Spring catalogue, slow drop
live I T A
title
lede
body · portableText

Each piece carries the hours it was made in. Linen, oak, oxidized brass — six considered things this season. Mailed from Casper, Wyoming, the day they're ordered.

Available now, as long as they last.

cover · image
spring-cover.jpg
06 — How it ships

Six weeks,
schema first.

  1. w 01

    Schema design

    Audit, model the documents, types, references. Lock the editor experience as a deliverable.

  2. w 02

    Studio scaffold

    Studio scaffolded, schemas in TypeScript, environments configured (production / staging / dev).

  3. w 02–04

    Custom Studio + frontend

    Custom inputs, desk structure, Studio tools. Frontend with GROQ + ISR. Real-time presence tuned.

  4. w 04

    Migration + SEO

    Migration scripts (reversible), staging dry-runs. Schema, sitemaps, redirects, hreflang.

  5. w 06

    Editor onboarding + launch

    Loom walkthroughs, role setup, dry-run publishes. DNS cutover. Slack handoff.

  6. Care plan

    Schema upkeep, Studio maintenance, perf monitoring, monthly review. Features, not tickets.

Booking Q3 2026 · Avg engagement: 6 weeks · Reply within 24h