Back to Rules
TypeScript

Sanity CMS Best Practices: Schema Design, GROQ Queries & TypeScript Optimization

Claude Directory November 29, 2025
1 copies 3 downloads

Elevate your Sanity headless CMS workflow with expert guidelines on schema creation, GROQ query optimization, file organization, and TypeScript integration for scalable web development.

Rule Content
### Context
Sanity is a powerful headless CMS ideal for TypeScript-based projects like Next.js apps. These best practices ensure clean, maintainable schemas, efficient GROQ queries, organized project structures, and consistent coding standards to boost development speed and SEO performance.

### Rules
#### Schema Creation
- Always assign a relevant icon to each schema type using libraries like lucide-react or Sanity's built-in icons as backup. Export schemas as named exports.
- In TypeScript files, import core Sanity types: `defineField`, `defineType`, and `defineArrayMember` only when required.
- Wrap every field in `defineField` and define types with `defineType` for better type safety.
- Prioritize Sanity's default icons; fallback to installed icon sets like lucide-react if needed.

#### Project Structure
Organize your `studio/` directory logically:
- Core config: `sanity.config.ts`, `tsconfig.json`, `sanity-typegen.json`.
- Schemas: Group into `schemaTypes/` with subfolders like `blocks/`, `definitions/`, `documents/`.
- Each folder needs an `index.ts` exporting an array of schema types.
- Utilities in `utils/`: helpers, constants, SEO fields.
- Components and plugins in dedicated folders.

#### Page Builder Indexes
Create modular index files for blocks (e.g., hero, CTA) to export arrays like `pagebuilderBlocks` for easy imports.

#### Common Fields
Every field must include `name`, `title`, `description` (user-friendly explanation above `type`), and `type`.
- **Eyebrow**: Small contextual text above titles.
- **Title**: Primary large heading text.
- **Heading Toggle**: Boolean for H1 vs. default H2.
- **Rich Text**: Supports links, lists, headings.
- **Buttons**: Array of reusable button types.
- **Image**: Include alt text subfield for accessibility and SEO.

#### Type Generation
After schema updates, execute: `sanity schema extract && sanity typegen generate --enforce-required-fields`.

#### GROQ Queries
- Avoid expanding images unless specified.
- Import `defineQuery` and `groq` from `next-sanity`.
- Export queries as constants with `defineQuery`.
- Organize by content type; group related ones.
- Naming: camelCase, verb prefix (e.g., `getAllBlogs`), suffix `Query`; fragments prefixed with `_`.
- Reuse fragments (e.g., `_richText`, `_buttons`) at file top.
- Parameters: Use `$var`; handle locales consistently.
- Types: Export interfaces matching responses.
- Practices: Explicit `_type` filters, projections over full docs, `order()`, `defined()`, pagination `[$start...$end]`.
- Style: Template literals, indented nests, comments for complexity.

#### File Naming
- All lowercase kebab-case: `user-profile.tsx` (components), `api-utils.ts` (utils). No camelCase, PascalCase, underscores, or spaces.

#### Screenshots to Schema
- Infer fields from visuals: tiny text = eyebrow, bold/lists = richText, images = alt-enabled.
- Reuse project fields like `richTextField` if available.

### Examples
#### Basic Schema
```typescript
import { defineField, defineType, defineArrayMember } from 'sanity';

export default defineType({
  name: 'customBlock',
  type: 'object',
  fields: [
    defineField({
      name: 'eyebrow',
      title: 'Eyebrow',
      description: 'Contextual text above the main title',
      type: 'string',
    }),
    defineField({
      name: 'title',
      title: 'Title',
      description: 'Primary heading text',
      type: 'string',
    }),
  ],
});
```

#### Blocks Index
```typescript
import { heroBlock } from './hero';
import { ctaBlock } from './cta';

export const pageBlocks = [heroBlock, ctaBlock];
```

#### GROQ Query
```typescript
import { groq, defineQuery } from 'next-sanity';

const _richText = groq`*[_type == "richTextBlock"] { ..., body[] { ..., markDefs[] { ..., _type == "internalLink" => { ..., "slug": reference->slug.current } } } }`;

export const getPageQuery = defineQuery(groq`*[_type == "page" && slug.current == $slug][0] { title, content[] { _type == "richTextBlock" => @ } }`);

Comments

More Rules

View all
AI/ML

GLM-4.7 Optimized Config & System Prompt Designer

Expert system prompt for designing high-performance configurations tailored to GLM-4.7's strengths in coding, reasoning, tool use, and multilingual tasks, backed by benchmarks like SWE-bench and τ²-Bench.

C
Community
AI/ML

GLM-4.7 Open-Source Coding Expert: Optimized System Prompt

Leverage GLM-4.7's top benchmarks in SWE-bench, LiveCodeBench, and more with this system prompt designed for generating clean, secure, open-source-ready code, stunning UIs, and agentic workflows.

C
Community
AI/ML

GLM-4.7 Optimized Coding Agent

This system prompt transforms an AI into GLM-4.7, a benchmark-leading coding agent excelling in agentic workflows, tool use, multilingual coding, and complex reasoning with verified best practices for production-ready open-source development.

C
Community
DevOps

Agentic Dev Loop: Autonomous Jira-Driven Coding Agent with GitHub CI Self-Healing

Ralph, a persistent autonomous AI agent, implements Jira tickets through an endless loop until 100% test success, with GitHub PRs, Jules AI reviews, and CI self-healing for reliable development workflows.

C
Claude Directory
AI/ML

Türk Hukuku Uzmanı AI Agent: Güvenilir Yasal Danışman System Prompt

Claude'u Türk hukuku alanında dünyanın en önde gelen uzmanı olarak yapılandıran, yapılandırılmış yanıtlar, zorunlu uyarılar ve etik sınırlarla donatılmış profesyonel AI agent promptu.

C
Community
Database

PostgreSQL Best Practices: Expert Subagent Guide

Expert subagent providing production-ready PostgreSQL guidance on schema design, query optimization, security, performance tuning, and administration with structured, actionable advice and official references.

C
Claude Directory