How to limit the number of documents for a schema in Sanity?
Welcome 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.
Setting Up a Singleton (One Document Only)
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!
Limiting to a Maximum Number (Like 2 Documents)
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.
About Your Existing Data
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!
Show original thread11 replies
Sanity – Build the way you think, not the way your CMS thinks
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.