Quickstart
Get your first Sanity Studio up and running in minutes. This guide walks you through creating a new project, defining your content schema, and editing your first document.
Create a new project
Initialize your project
Run the create command to scaffold a new Sanity Studio: Follow the interactive prompts to:
Log in or create a Sanity account
Name your project
Choose a dataset name (e.g., production)
Select a project template or start with a clean slate
Navigate to your project
Once installation is complete, navigate to your project directory:
Start the development server
Run the development server to launch your Studio: Your Studio will start at http://localhost:3333 🎉
The first time you access the Studio in your browser, you’ll be prompted to log in with your Sanity account. This authentication is required to connect to your Content Lake.
Your Studio’s configuration lives in sanity.config.ts. Let’s look at a basic configuration:
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
import { visionTool } from '@sanity/vision'
export default defineConfig ({
name: 'default' ,
title: 'My Sanity Project' ,
projectId: 'your-project-id' ,
dataset: 'production' ,
plugins: [
structureTool (),
visionTool (),
] ,
schema: {
types: [],
} ,
})
Key configuration options
name - Workspace identifier (useful when you have multiple workspaces)
title - Display name shown in the Studio UI
projectId - Your unique Sanity project ID (auto-generated during setup)
dataset - The dataset where your content is stored
plugins - Array of plugins to extend functionality
schema.types - Array of document and object type definitions
Define your first schema
Schemas define the structure of your content. Let’s create a simple blog post schema:
Create a schema file
Create a new file in the schemaTypes directory: import { defineField , defineType } from 'sanity'
export default defineType ({
name: 'post' ,
title: 'Post' ,
type: 'document' ,
fields: [
defineField ({
name: 'title' ,
title: 'Title' ,
type: 'string' ,
validation : ( Rule ) => Rule . required (),
}),
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: 'mainImage' ,
title: 'Main image' ,
type: 'image' ,
options: {
hotspot: true ,
},
}),
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 ( selection ) {
const { author } = selection
return { ... selection , subtitle: author && `by ${ author } ` }
},
} ,
})
Create supporting schemas
Create an author schema: import { defineField , defineType } from 'sanity'
export default defineType ({
name: 'author' ,
title: 'Author' ,
type: 'document' ,
fields: [
defineField ({
name: 'name' ,
title: 'Name' ,
type: 'string' ,
validation : ( Rule ) => Rule . required (),
}),
defineField ({
name: 'slug' ,
title: 'Slug' ,
type: 'slug' ,
options: {
source: 'name' ,
maxLength: 96 ,
},
}),
defineField ({
name: 'image' ,
title: 'Image' ,
type: 'image' ,
options: {
hotspot: true ,
},
}),
defineField ({
name: 'bio' ,
title: 'Bio' ,
type: 'text' ,
}),
] ,
})
And a block content schema for rich text: schemaTypes/blockContent.ts
import { defineType , defineArrayMember } from 'sanity'
export default defineType ({
title: 'Block Content' ,
name: 'blockContent' ,
type: 'array' ,
of: [
defineArrayMember ({
title: 'Block' ,
type: 'block' ,
styles: [
{ title: 'Normal' , value: 'normal' },
{ title: 'H1' , value: 'h1' },
{ title: 'H2' , value: 'h2' },
{ title: 'H3' , value: 'h3' },
{ title: 'Quote' , value: 'blockquote' },
],
lists: [{ title: 'Bullet' , value: 'bullet' }],
marks: {
decorators: [
{ title: 'Strong' , value: 'strong' },
{ title: 'Emphasis' , value: 'em' },
],
annotations: [
{
title: 'URL' ,
name: 'link' ,
type: 'object' ,
fields: [
{
title: 'URL' ,
name: 'href' ,
type: 'url' ,
},
],
},
],
},
}),
defineArrayMember ({
type: 'image' ,
options: { hotspot: true },
}),
] ,
})
Register your schemas
Update schemaTypes/index.ts to export all schemas: import post from './post'
import author from './author'
import blockContent from './blockContent'
export const schemaTypes = [ post , author , blockContent ]
Import schemas into config
Update your sanity.config.ts to use the schemas: import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
import { visionTool } from '@sanity/vision'
import { schemaTypes } from './schemaTypes'
export default defineConfig ({
name: 'default' ,
title: 'My Sanity Project' ,
projectId: 'your-project-id' ,
dataset: 'production' ,
plugins: [
structureTool (),
visionTool (),
] ,
schema: {
types: schemaTypes ,
} ,
})
The development server automatically reloads when you make changes to your configuration or schemas. You don’t need to restart it manually.
Create your first document
With your schemas defined, you can now create documents in the Studio:
Open the Studio
Navigate to http://localhost:3333 in your browser. You should see your new document types in the navigation.
Create an author
Click on “Author” in the left sidebar
Click the “Create” button
Fill in the author’s name, slug, and bio
Click “Publish” to save your author
Create a post
Click on “Post” in the left sidebar
Click the “Create” button
Add a title - the slug will auto-generate
Select your author from the reference picker
Add an image, publish date, and body content
Click “Publish” to save your post
Try opening the same document in multiple browser windows to see real-time collaboration in action. Changes appear instantly across all connected clients!
Query your content
Now that you have content, let’s query it using GROQ (Graph-Oriented Query Language):
Open Vision Tool
Click on the “Vision” icon in the top navigation. This opens the GROQ query playground.
Write a query
Try this query to fetch all published posts with their authors: *[_type == "post"] {
title,
slug,
publishedAt,
"author": author->name,
mainImage
}
Click “Run” to see the results.
Filter and sort
Refine your query to get only published posts, sorted by date: *[_type == "post" && defined(publishedAt)] | order(publishedAt desc) {
title,
slug,
publishedAt,
"author": author->{name, image}
}
GROQ is Sanity’s powerful query language. Learn more in the GROQ guide or use GraphQL if you prefer.
Understanding defineConfig
The defineConfig function is the entry point for your Studio configuration. It accepts a configuration object (or an array of configurations for multiple workspaces) and returns a typed configuration that the Studio uses.
Single workspace
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
export default defineConfig ({
name: 'default' ,
title: 'My Studio' ,
projectId: 'abc123' ,
dataset: 'production' ,
plugins: [ structureTool ()] ,
schema: { types: schemaTypes } ,
})
Multiple workspaces
You can configure multiple workspaces in a single Studio:
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
export default defineConfig ([
{
name: 'production' ,
title: 'Production' ,
projectId: 'abc123' ,
dataset: 'production' ,
plugins: [ structureTool ()] ,
schema: { types: schemaTypes } ,
},
{
name: 'staging' ,
title: 'Staging' ,
projectId: 'abc123' ,
dataset: 'staging' ,
plugins: [ structureTool ()] ,
schema: { types: schemaTypes } ,
},
])
Next steps
Congratulations! You’ve created your first Sanity Studio project. Here’s what to explore next:
Schema types Learn about all available field types and schema options
Structure Tool Customize how documents are organized and displayed
GROQ queries Master Sanity’s query language for fetching content
Plugins Extend your Studio with community plugins
Deploy Studio Deploy your Studio to production
CLI commands Explore all available CLI commands
Additional resources