
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeWelcome to Sanity! Glad you're enjoying it! 🎉
Yes, you can limit the number of documents for a schema type! For your home page example where you only want one document, you'll want to create what's called a singleton document. For limiting to a maximum number (like 2), there's a different approach.
To create a singleton, you need to configure three things in your sanity.config.ts file, as explained in the singleton document guide:
1. Structure Builder - Create a direct link to the single document:
export default defineConfig({
// ... other config
plugins: [
structureTool({
structure: (S) =>
S.list()
.title('Content')
.items([
S.listItem()
.title('Home Page')
.id('homePage')
.child(
S.document()
.schemaType('homePage')
.documentId('homePage')
),
// ... other items
])
})
]
})2. Filter Templates - Remove it from the "New document" menu:
const singletonTypes = new Set(['homePage'])
export default defineConfig({
// ... other config
schema: {
types: schemaTypes,
templates: (templates) =>
templates.filter(({ schemaType }) => !singletonTypes.has(schemaType))
}
})3. Filter Document Actions - Remove duplicate/delete actions:
const singletonActions = new Set(['publish', 'discardChanges', 'restore'])
export default defineConfig({
// ... other config
document: {
actions: (input, context) =>
singletonTypes.has(context.schemaType)
? input.filter(({ action }) => action && singletonActions.has(action))
: input
}
})Important: Create the document instance first (before adding these configurations), since you're hiding the "create new" UI!
For limiting to a specific maximum (not just one), you can use the document.newDocumentOptions configuration to dynamically hide the create button when the limit is reached. Here's an example:
export default defineConfig({
// ... other config
document: {
newDocumentOptions: async (prev, { creationContext, getClient }) => {
// Only filter for specific schema types
const limitedTypes = ['testimonial', 'featuredPost']
const limits = {
testimonial: 2,
featuredPost: 3
}
// Get filtered templates
const filtered = await Promise.all(
prev.map(async (template) => {
const schemaType = template.templateId
if (!limitedTypes.includes(schemaType)) {
return template
}
// Query to count existing documents
const client = getClient({ apiVersion: '2024-11-01' })
const count = await client.fetch(
`count(*[_type == $type])`,
{ type: schemaType }
)
// Hide template if limit reached
if (count >= limits[schemaType]) {
return null
}
return template
})
)
return filtered.filter(Boolean)
}
}
})This approach queries your dataset to count existing documents and hides the creation option when the limit is reached.
As noted in this community answer, switching to the Structure Builder won't delete your existing content. Your studio already uses the Structure Builder—you're just not customizing it yet. However, for singleton documents, you may need to recreate them with the specific document ID you define in your structure configuration.
This singleton pattern is super common for things like site settings, home pages, about pages, and global configuration!
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store