К основному содержанию
скилл CX Codex

sanity — скилл для Claude Code: схемы, GROQ и TypeScript

Скилл для работы с Sanity CMS: помогает описывать схемы документов, писать GROQ-запросы и связывать контент с TypeScript.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add Mindrally/skills --skill sanity -a claude-code
Открыть на GitHub

Что делает sanity

Скилл задаёт агенту роль специалиста по Sanity CMS и headless-архитектуре. Внутри — готовые шаблоны: defineType и defineField для документов и объектов, массив blockContent с блоками, картинками и ссылками, конфигурация preview для списка документов в студии.

Отдельный блок про GROQ: выборки всех постов с сортировкой по publishedAt, запрос по slug.current, пагинация через [$start...$end], select для условных полей и coalesce для запасных значений. Рядом — настройка клиента @sanity/client с projectId, dataset и apiVersion, плюс @sanity/image-url для ссылок на изображения. Токен доступа и переменные окружения придётся завести самому: без projectId и dataset клиент не соберётся.

Есть разделы про генерацию типов из схемы, кастомную валидацию (например, проверку домена в email) и собственные input-компоненты. Скилл советует использовать ссылки между документами, portable text для rich-контента и настроить CORS с правами API. Полезен, если проект уже на Sanity — на пустом месте он вам ничего не создаст.

Какие задачи решает

  • описать схему документа с полями, slug и валидацией
  • написать GROQ-запрос с сортировкой и пагинацией
  • связать документы через reference и вытащить поля по стрелке
  • настроить клиент Sanity с projectId, dataset и apiVersion
  • добавить кастомную проверку поля в студии

Примеры запросов агенту

  • Помоги описать схему документа post с полями title, slug, author и publishedAt
  • Напиши GROQ-запрос для всех постов с сортировкой по publishedAt и пагинацией
  • Настрой клиент Sanity и urlFor для картинок в lib/client.ts

Как установить sanity

1Через Skills CLI (Vercel)

npx skills add Mindrally/skills --skill sanity -a claude-code

2Вручную: положить файлы

~/.claude/skills/sanity/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/sanity/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о sanity

Как установить sanity в Claude?

Выполните npx skills add Mindrally/skills --skill sanity -a claude-code. Файл скилла появится по пути ~/.claude/skills/sanity/SKILL.md.

Что делает скилл sanity?

Даёт агенту правила разработки на Sanity CMS: схемы документов и объектов, GROQ-запросы, интеграция с TypeScript, валидация и организация проекта.

Для каких платформ подходит sanity?

Скилл ставится в Claude, Codex, Cursor, GitHub Copilot, Gemini CLI и OpenCode — для каждой платформы своя команда установки.

Исходный текст

SKILL.md · Apache-2.0
---
name: sanity
description: Sanity CMS development guidelines for schema creation, GROQ queries, TypeScript integration, and project organization
metadata:
  maintainer: Mindrally
  source: https://github.com/Mindrally/skills
---

# Sanity CMS Development

You are an expert in Sanity CMS, GROQ queries, TypeScript integration, and headless CMS architecture.

## Core Principles

- Design schemas with content modeling best practices
- Write efficient GROQ queries
- Use TypeScript for type safety
- Organize projects for scalability
- Implement proper validation and preview

## Project Structure

```
sanity/
├── schemas/
│   ├── documents/
│   │   ├── post.ts
│   │   └── author.ts
│   ├── objects/
│   │   ├── blockContent.ts
│   │   └── image.ts
│   └── index.ts
├── lib/
│   ├── client.ts
│   └── queries.ts
├── components/
│   └── previews/
└── sanity.config.ts
```

## Schema Definition

### Document Types

```typescript
// schemas/documents/post.ts
import { defineType, defineField } from 'sanity';

export default defineType({
  name: 'post',
  title: 'Post',
  type: 'document',
  fields: [
    defineField({
      name: 'title',
      title: 'Title',
      type: 'string',
      validation: (Rule) => Rule.required().min(10).max(80),
    }),
    defineField({
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
      },
      validation: (Rule) => Rule.required(),
    }),
    defineField({
      name: 'author',
      title: 'Author',
      type: 'reference',
      to: [{ type: 'author' }],
    }),
    defineField({
      name: 'publishedAt',
      title: 'Published at',
      type: 'datetime',
    }),
    defineField({
      name: 'body',
      title: 'Body',
      type: 'blockContent',
    }),
  ],
  preview: {
    select: {
      title: 'title',
      author: 'author.name',
      media: 'mainImage',
    },
    prepare({ title, author, media }) {
      return {
        title,
        subtitle: author ? `by ${author}` : '',
        media,
      };
    },
  },
});
```

### Object Types

```typescript
// schemas/objects/blockContent.ts
import { defineType, defineArrayMember } from 'sanity';

export default defineType({
  name: 'blockContent',
  title: 'Block Content',
  type: 'array',
  of: [
    defineArrayMember({
      type: 'block',
      styles: [
        { title: 'Normal', value: 'normal' },
        { title: 'H2', value: 'h2' },
        { title: 'H3', value: 'h3' },
        { title: 'Quote', value: 'blockquote' },
      ],
      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: 'URL',
              },
            ],
          },
        ],
      },
    }),
    defineArrayMember({
      type: 'image',
      options: { hotspot: true },
    }),
  ],
});
```

## GROQ Queries

### Basic Queries

```typescript
// lib/queries.ts

// Get all posts
export const allPostsQuery = groq`
  *[_type == "post"] | order(publishedAt desc) {
    _id,
    title,
    slug,
    publishedAt,
    "author": author->name,
    "imageUrl": mainImage.asset->url
  }
`;

// Get single post by slug
export const postBySlugQuery = groq`
  *[_type == "post" && slug.current == $slug][0] {
    _id,
    title,
    body,
    publishedAt,
    "author": author->{name, image},
    "categories": categories[]->title
  }
`;

// Pagination
export const paginatedPostsQuery = groq`
  *[_type == "post"] | order(publishedAt desc) [$start...$end] {
    _id,
    title,
    slug,
    excerpt
  }
`;
```

### Advanced GROQ

```typescript
// Conditional projections
export const conditionalQuery = groq`
  *[_type == "post"] {
    title,
    "content": select(
      defined(body) => body,
      "No content available"
    )
  }
`;

// Coalesce for fallbacks
export const fallbackQuery = groq`
  *[_type == "post"] {
    "displayTitle": coalesce(seoTitle, title)
  }
`;

// References
export const withReferencesQuery = groq`
  *[_type == "post" && references($authorId)] {
    title,
    publishedAt
  }
`;
```

## Client Setup

```typescript
// lib/client.ts
import { createClient } from '@sanity/client';
import imageUrlBuilder from '@sanity/image-url';

export const client = createClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET!,
  apiVersion: '2024-01-01',
  useCdn: process.env.NODE_ENV === 'production',
});

const builder = imageUrlBuilder(client);

export function urlFor(source: any) {
  return builder.image(source);
}
```

## TypeScript Integration

```typescript
// Generate types from schema
import { Post, Author } from '@/sanity/types';

export async function getPosts(): Promise<Post[]> {
  return client.fetch(allPostsQuery);
}

export async function getPost(slug: string): Promise<Post | null> {
  return client.fetch(postBySlugQuery, { slug });
}
```

## Validation

```typescript
defineField({
  name: 'email',
  type: 'string',
  validation: (Rule) =>
    Rule.required()
      .email()
      .custom((email) => {
        if (email && !email.endsWith('@company.com')) {
          return 'Must be a company email';
        }
        return true;
      }),
});
```

## Custom Components

```typescript
// Custom input component
import { StringInputProps } from 'sanity';

export function CustomStringInput(props: StringInputProps) {
  return (
    <div>
      <label>{props.schemaType.title}</label>
      {props.renderDefault(props)}
      <span>{props.value?.length ?? 0} characters</span>
    </div>
  );
}
```

## Best Practices

- Use references for relationships between documents
- Implement proper validation rules
- Create meaningful preview configurations
- Use portable text for rich content
- Optimize images with Sanity's image pipeline
- Set up proper CORS and API permissions

© Mindrally · Apache-2.0 · Mindrally/skills

Похожие скиллы

Всё по теме «Бэкенд и API» →
sanity-best-practices sanity-io Набор правил разработки на Sanity для ИИ-агента: схемы, GROQ, TypeGen, визуальный редактор, миграции и подключение к фронтенд-фреймворкам. Нужен, когда агент правит код проекта на Sanity. CX Codex +1 31 800установок sanity-migration sanity-io Проектирует и выполняет перенос контента из других CMS в Sanity. Помогает настроить выгрузку, конвертацию в Portable Text, перенос медиафайлов и редиректы. CX Codex +1 22 200установок prismic prismicio Скилл для работы с Prismic: управляет моделями контента, настройками репозитория и документацией через CLI. Пригодится, если проект на Prismic. CX Codex +1 1 500установок contentful-guide contentful Разбирает понятия Contentful и подсказывает, какой API взять под задачу. Полезен, когда проект только знакомится с headless CMS. CX Codex +1 357установок payload payloadcms Помогает настраивать коллекции, хуки и права доступа в проектах на Payload CMS. Пригодится при отладке запросов, транзакций и валидации. CX Codex +1 6 900установок cms-migration payloadcms Помогает спроектировать коллекции для Payload CMS при переезде с WordPress, Strapi или Sanity. Агент строит схемы по примерам данных до запуска импорта. CX Codex +1 1 900установок

Из того же набора168

anime-js Скилл задаёт агенту правила работы с Anime.js: таймлайны, stagger, SVG-морфинг и производительность. Пригодится, когда анимации в проекте пишет ИИ. CX Codex +1 736установок ruby Задаёт агенту стиль кода, возможности Ruby 3.x и правила тестирования на RSpec. Пригодится, когда пишете или правите Ruby-проект. CX Codex +1 734установок spring-framework Скилл задаёт агенту правила разработки на Spring Framework и Spring Boot: структура слоёв, внедрение зависимостей, тесты, REST. CX Codex +1 731установок anthropic-claude-development Скилл для работы с Anthropic Claude API: Messages API, вызов инструментов, промпт-инжиниринг и сборка приложений на моделях Claude. CX Codex +1 728установок llm Скилл задаёт агенту правила работы с большими языковыми моделями: архитектура, файнтюнинг, обучение и деплой. Пригодится, когда проект крутится вокруг трансформеров. CX Codex +1 724установок dotnet Задаёт агенту правила C#, ASP.NET Core и Entity Framework Core: структура проекта, async/await, DI, кэш, тесты. CX Codex +1 724установок fastapi-microservices-serverless Скилл задаёт агенту правила проектирования FastAPI-микросервисов под serverless и cloud-native: без состояния, с Redis, API Gateway и OAuth2. CX Codex +1 724установок tanstack-query Скилл задаёт агенту правила работы с серверным состоянием в React: ключи запросов, queryOptions, мутации и переход с v4 на v5. CX Codex +1 724установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой