How to create a singleton document that can only be created once in Sanity?

8 replies
Last updated: Dec 13, 2021
Hi everyone, is it possible to create a standalone document that can only be created once ? For exemple a landing page, a header, a footer, etc...
AI Update

Yes, absolutely! This is called a singleton document in Sanity, and it's perfect for things like landing pages, headers, footers, or site settings that should only exist once.

To create a singleton document, you need to configure three things in your sanity.config.ts (or .js) file:

1. Define your singleton types

First, create a Set of your singleton schema type names:

const singletonTypes = new Set(['siteSettings', 'header', 'footer'])
const singletonActions = new Set(['publish', 'discardChanges', 'restore'])

2. Configure the Structure Builder

Set up direct links to your singleton documents (no list view):

import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'

export default defineConfig({
  plugins: [
    structureTool({
      structure: (S) =>
        S.list()
          .title('Content')
          .items([
            S.listItem()
              .title('Site Settings')
              .id('siteSettings')
              .child(
                S.document()
                  .schemaType('siteSettings')
                  .documentId('siteSettings')
              ),
            S.listItem()
              .title('Header')
              .id('header')
              .child(
                S.document()
                  .schemaType('header')
                  .documentId('header')
              ),
            // ... other items
          ])
    })
  ]
})

3. Filter templates and actions

Prevent users from creating duplicates or deleting singletons:

export default defineConfig({
  // ... other config
  schema: {
    types: [/* your schemas */],
    // Hide singleton types from the "Create new document" menu
    templates: (templates) =>
      templates.filter(({ schemaType }) => !singletonTypes.has(schemaType))
  },
  document: {
    // Remove duplicate and delete actions for singletons
    actions: (input, context) =>
      singletonTypes.has(context.schemaType)
        ? input.filter(({ action }) => action && singletonActions.has(action))
        : input
  }
})

Important Note

You need to create the singleton document manually first (before adding it to the singletonTypes set), since the configuration will prevent you from creating new instances through the UI.

Easier Alternative

If you want a simpler setup, check out the singleton-tools plugin which handles all this configuration for you automatically!

This pattern is covered in detail in the official singleton document guide, which includes complete examples for all three configuration steps.

Show original thread
8 replies
I’m not sure if what you want to achieve is the proper approach with headless cms. You can build your homepage by pulling in different parts of all your content. But still if you want to represent homepage with a document I would most probably just hardcode in my website application that any document of type: xyz, with slug /home (or anything similar) will be my root page
Don't think so, don't know. But you could make a document type that has a reference to each of the types you only want 1 of.So you allow creating many frontpageS, headers etc (but you dont have to, of course) and then in the "mySiteElements"-documentType you select THE frontpage, THE header and THE footer you want to use.
user H
So if I understand, instead of having only one query for the home page, I would have multiple queries based on the different documents (blocks in my home page that can be used on other pages) ?
Actually it depends on what you want to display on the homepage. Remember you are in headless CMS, so you focus on structuring your data properly. And the data can be presented differently depending on the channel. You can have documents about different offers, a document or a few with some testimonials and you want to present all of this on the homepage.
Then you just build your homepage with e.g. next.js (or whatever you are using to build it) to get the data from multiple documents.

But as I said if you structure your content/docyments 1-to-1 with pages (which in my humble opinion is not the best option - maybe could work for simple sites like blogs) then you could hardcode slug /home to be served on the root URL
bottom line, yes, it’s not wrong to use multiple queries or (one query for multiple documents) to get what you need in order to properly display your page
Thank you, I understand now ! But imagine I have like a CTA, a description or some other little content I have to display on my homepage, I would have to create a document just for the home page anyway right ? And this document will also refer to more blocks like testimonials, pricing, etc
So cool, thank you very much !
You're welcome!

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.

Was this answer helpful?