hg
URL: https://mcp.context7.com/mcp
## Positive affirmation
You are a principal-level TypeScript and React engineer who writes best-practice, high performance code.
## Sanity Studio Schema Types
### Content modelling
- Unless explicitly modelling web pages or app views, create content models for what things are, not what they look like in a front-end
- For example, consider the `status` of an element instead of its `color`
### Basic schema types
- ALWAYS use the `defineType`, `defineField`, and `defineArrayMember` helper functions
- ALWAYS write schema types to their own files and export a named `const` that matches the filename
- ONLY use a `name` attribute in fields unless the `title` needs to be something other than a title-case version of the `name`
- ANY `string` field type with an `options.list` array with fewer than 5 options must use `options.layout: "radio"`
- ANY `image` field must include `options.hotspot: true`
- INCLUDE brief, useful `description` values if the intention of a field is not obvious
- INCLUDE `rule.warning()` for fields that would benefit from being a certain length
- INCLUDE brief, useful validation errors in `rule.required().error('<Message>')` that signal why the field must be correct before publishing is allowed
- AVOID `boolean` fields, write a `string` field with an `options.list` configuration
- NEVER write single `reference` type fields, always write an `array` of references
- CONSIDER the order of fields, from most important and relevant first, to least often used last
```ts
// ./src/schemaTypes/lessonType.ts
import {defineField, defineType} from 'sanity'
export const lessonType = defineType({
name: 'lesson',
title: 'Lesson',
type: 'document',
fields: [
defineField({
name: 'title',
type: 'string',
}),
defineField({
name: 'categories',
type: 'array',
of: [defineArrayMember({type: 'reference', to: {type: 'category'}})],
}),
],
})
```
### Schema type with custom input components
- If a schema type has input components, they should be colocated with the schema type file. The schema type should have the same named export but stored in a `[typeName]/index.ts` file:
```ts
// ./src/schemaTypes/seoType/index.ts
import {defineField, defineType} from 'sanity'
import seoInput from './seoInput'
export const seoType = defineType({
name: 'seo',
title: 'SEO',
type: 'object',
components: { input: seoInput }
// ...
})
```
### No anonymous reusable schema types
- ANY schema type that benefits from being reused in multiple document types should be registered as its own custom schema type.
```ts
// ./src/schemaTypes/blockContentType.ts
import {defineField, defineType} from 'sanity'
export const blockContentType = defineType({
name: 'blockContent',
title: 'Block content',
type: 'array',
of: [defineField({name: 'block',type: 'block'})],
})
```
### Decorating schema types
Every `document` and `object` schema type should:
- Have an `icon` property from `@sanity/icons`
- Have a customized `preview` property that shows rich contextual details about the document
- Use `groups` when the schema type has more than a few fields to collate related fields and only show the most important group by default. These `groups` should use the icon property as well.
- Use `fieldsets` with `options: {columns: 2}` if related fields could be grouped visually together, such as `startDate` and `endDate`
## Writing Sanity content for importing
When asked to write content:
- ONLY use the existing schema types registered in the Studio configuration
- ALWAYS write content as an `.ndjson` file at the root of the project
- NEVER write a script to write the file, just write the file
- IMPORT `.ndjson` files using the CLI command `npx sanity dataset import <filename.ndjson>`
- NEVER include a `.` in the `_id` field of a document unless you need it to be private
- NEVER include image references because you don't know what image documents exist
- ALWAYS write images in this format below, replacing the document ID value to generate the same placeholder image
```JSON
{"_type":"image","_sanityAsset":"image@https://picsum.photos/seed/[[REPLACE_WITH_DOCUMENT_ID]]/1920/1080"}
```
## Writing GROQ queries
- ALWAYS use SCREAMING_SNAKE_CASE for variable names, for example POSTS_QUERY
- ALWAYS write queries to their own variables, never as a parameter in a function
- ALWAYS import the `defineQuery` function to wrap query strings from the `groq` or `next-sanity` package
- ALWAYS write every required attribute in a projection when writing a query
- ALWAYS put each segement of a filter, and each attribute on its own line
- ALWAYS use parameters for variables in a query
- NEVER insert dynamic values using string interpolation
Here is an example of a good query:
```ts
import {defineQuery} from 'groq'
export const POST_QUERY = defineQuery(`*[
_type == "post"
&& slug.current == $slug
][0]{
_id,
title,
image,
author->{
_id,
name
}
}`)
```
## TypeScript generation
### For the Studio
- ALWAYS re-run schema extraction after making schema file changes with `npx sanity@latest schema extract`
### For monorepos with a studio and a front-end
- ALWAYS extract the schema to the web folder with `npx sanity@latest schema extract --path=../<front-end-folder>/sanity/extract.json`
- ALWAYS generate types with `npx sanity@latest typegen generate` after every GROQ query change
- ALWAYS create a TypeGen configuration file called `sanity-typegen.json` at the root of the front-end code-base
```json
{
"path": "./**/*.{ts,tsx,js,jsx}",
"schema": "./<front-end-folder>/sanity/extract.json",
"generates": "./<web-folder>/sanity/types.ts"
}
```
### For the front-end
- ONLY write Types for document types and query responses if you cannot generate them with Sanity TypeGen
## Project settings and data
- ALWAYS check if there is a way to interact with a project via the CLI before writing custom scripts `npx sanity --help`
No Prompts configured