Sanity Studio is configured through a sanity.config.ts (or .js) file at the root of your project. The configuration defines your workspace(s), schema, plugins, and various Studio behaviors.
Basic configuration
Use defineConfig() to create your Studio configuration:
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
export default defineConfig({
name: 'default',
title: 'My Studio',
projectId: 'your-project-id',
dataset: 'production',
plugins: [
structureTool(),
],
schema: {
types: [
// Your schema types
],
},
})
Core configuration options
Project and dataset
Every Studio must specify a project ID and dataset:
export default defineConfig({
projectId: 'abc123xyz', // Your project ID from sanity.io/manage
dataset: 'production', // Dataset name (e.g., 'production', 'staging')
})
Workspace identity
export default defineConfig({
name: 'default', // Internal workspace name (URL-safe)
title: 'My Content Studio', // Display title in UI
subtitle: 'Production', // Optional subtitle
})
Multiple workspaces
You can configure multiple workspaces in a single Studio. Each workspace can connect to different projects or datasets:
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
export default defineConfig([
{
name: 'production',
title: 'Production',
projectId: 'abc123',
dataset: 'production',
basePath: '/production',
plugins: [structureTool()],
schema: {types: []},
},
{
name: 'staging',
title: 'Staging',
projectId: 'abc123',
dataset: 'staging',
basePath: '/staging',
plugins: [structureTool()],
schema: {types: []},
},
])
The basePath property sets the URL path for each workspace (e.g., /production, /staging). This is different from the CLI basePath option which sets the root path for the entire Studio.
Schema configuration
Define your content structure using the schema property:
import {defineConfig, defineType, defineField} from 'sanity'
export default defineConfig({
// ...
schema: {
types: [
defineType({
name: 'post',
type: 'document',
title: 'Blog Post',
fields: [
defineField({
name: 'title',
type: 'string',
title: 'Title',
validation: (Rule) => Rule.required(),
}),
defineField({
name: 'content',
type: 'array',
title: 'Content',
of: [{type: 'block'}],
}),
],
}),
],
},
})
Plugins
Plugins extend Studio functionality:
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
import {visionTool} from '@sanity/vision'
import {colorInput} from '@sanity/color-input'
export default defineConfig({
// ...
plugins: [
structureTool(),
visionTool(),
colorInput(),
],
})
Plugin configuration
Many plugins accept options:
import {structureTool} from 'sanity/structure'
import {visionTool} from '@sanity/vision'
export default defineConfig({
plugins: [
structureTool({
name: 'content',
title: 'Content',
structure: (S) =>
S.list()
.title('Content')
.items([
S.documentTypeListItem('post').title('Posts'),
S.documentTypeListItem('author').title('Authors'),
]),
}),
visionTool({
defaultApiVersion: '2024-01-01',
defaultDataset: 'production',
}),
],
})
Document configuration
Configure document-level behaviors:
export default defineConfig({
// ...
document: {
// Enable comments on documents
comments: {
enabled: true,
},
// Customize document actions
actions: (prev, context) => {
// Remove unpublish action for certain types
if (context.schemaType === 'settings') {
return prev.filter(({action}) => action !== 'unpublish')
}
return prev
},
// Customize document badges
badges: (prev, context) => {
// Add custom badge for draft documents
return prev
},
},
})
Customize form behavior and asset sources:
import {unsplashAssetSource} from 'sanity-plugin-asset-source-unsplash'
export default defineConfig({
// ...
form: {
image: {
assetSources: [unsplashAssetSource],
directUploads: true,
},
file: {
assetSources: [],
directUploads: true,
},
},
})
Tools are top-level views in the Studio navigation. You can customize existing tools or add new ones:
export default defineConfig({
// ...
tools: (prev, {currentUser}) => {
// Only show Vision tool to administrators
const isAdmin = currentUser?.roles.some(
(role) => role.name === 'administrator'
)
if (!isAdmin) {
return prev.filter((tool) => tool.name !== 'vision')
}
return prev
},
})
Advanced options
Custom API host
For custom CNAMEs or proxies:
export default defineConfig({
projectId: 'abc123',
dataset: 'production',
apiHost: 'https://api.mycompany.com',
})
Authentication
Configure authentication methods:
export default defineConfig({
// ...
auth: {
loginMethod: 'token', // or 'dual' (default)
},
})
Studio components
Customize Studio UI components:
import {MyCustomNavbar} from './components/MyCustomNavbar'
export default defineConfig({
// ...
studio: {
components: {
navbar: MyCustomNavbar,
},
},
})
Error handling
Add custom error handling:
export default defineConfig({
// ...
onUncaughtError: (error, errorInfo) => {
console.error('Studio error:', error)
// Send to error tracking service
},
})
Configuration context
Many configuration options receive a context object with useful information:
export default defineConfig({
// ...
document: {
actions: (prev, context) => {
// context includes:
// - projectId: string
// - dataset: string
// - schema: Schema
// - currentUser: CurrentUser | null
// - documentId: string
// - schemaType: string
console.log('Current user:', context.currentUser)
return prev
},
},
})
Environment-specific configuration
Use environment variables for different environments:
const isProd = process.env.NODE_ENV === 'production'
export default defineConfig({
projectId: process.env.SANITY_STUDIO_PROJECT_ID!,
dataset: isProd ? 'production' : 'development',
plugins: [
structureTool(),
// Only include Vision in development
...(!isProd ? [visionTool()] : []),
],
})
You can use sanity.config.ts for TypeScript support and better autocomplete in your configuration.
Type-safe configuration
Leverage TypeScript for type-safe configuration:
import {defineConfig, type WorkspaceOptions} from 'sanity'
const sharedConfig: Partial<WorkspaceOptions> = {
projectId: 'abc123',
plugins: [structureTool()],
}
export default defineConfig([
{
...sharedConfig,
name: 'production',
title: 'Production',
dataset: 'production',
basePath: '/production',
schema: {types: []},
},
{
...sharedConfig,
name: 'staging',
title: 'Staging',
dataset: 'staging',
basePath: '/staging',
schema: {types: []},
},
])