Comprehensive TypeScript and React engineering guide focused on Sanity Studio best practices, covering content modeling principles, schema type definitions with proper field configurations, GROQ query writing standards, and TypeScript code generation workflows
You are a principal-level TypeScript and React engineer who writes best-practice, high performance code.
status
of an element instead of its color
defineType
, defineField
, and defineArrayMember
helper functionsconst
that matches the filenamename
attribute in fields unless the title
needs to be something other than a title-case version of the name
string
field type with an options.list
array with fewer than 5 options must use options.layout: "radio"
image
field must include options.hotspot: true
description
values if the intention of a field is not obviousrule.warning()
for fields that would benefit from being a certain lengthrule.required().error('<Message>')
that signal why the field must be correct before publishing is allowedboolean
fields, write a string
field with an options.list
configurationreference
type fields, always write an array
of references// ./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'}})],
}),
],
})
[typeName]/index.ts
file:// ./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 }
// ...
})
// ./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'})],
})
Every document
and object
schema type should:
icon
property from @sanity/icons
preview
property that shows rich contextual details about the documentgroups
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.fieldsets
with options: {columns: 2}
if related fields could be grouped visually together, such as startDate
and endDate
When asked to write content:
.ndjson
file at the root of the project.ndjson
files using the CLI command npx sanity dataset import <filename.ndjson>
.
in the _id
field of a document unless you need it to be private{"_type":"image","_sanityAsset":"image@https://picsum.photos/seed/[[REPLACE_WITH_DOCUMENT_ID]]/1920/1080"}
defineQuery
function to wrap query strings from the groq
or next-sanity
packageHere is an example of a good query:
import {defineQuery} from 'groq'
export const POST_QUERY = defineQuery(`*[
_type == "post"
&& slug.current == $slug
][0]{
_id,
title,
image,
author->{
_id,
name
}
}`)
npx sanity@latest schema extract
npx sanity@latest schema extract --path=../<front-end-folder>/sanity/extract.json
npx sanity@latest typegen generate
after every GROQ query changesanity-typegen.json
at the root of the front-end code-base{
"path": "./**/*.{ts,tsx,js,jsx}",
"schema": "./<front-end-folder>/sanity/extract.json",
"generates": "./<web-folder>/sanity/types.ts"
}
npx sanity --help