How to create singleton documents in Sanity?

13 replies
Last updated: Oct 11, 2022
Hi everyone!Does anyone know how I create single use documents? For example, for general company info like uploading the logo, company addresses etc. Or another use case, would be for a homepage of a website – whereby you'd only allow one – basically a single object, rather than an array
AI Update

Yes, what you're looking for is called a singleton document in Sanity. This is exactly designed for use cases like company settings, homepage content, or any other content that should only have one instance.

How to Create a Singleton

To properly set up a singleton document, you need to configure three things in your sanity.config.js file:

First, define which types should be singletons and customize your structure:

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

const singletonTypes = new Set(['settings', 'homepage'])

export default defineConfig({
  // ... other config
  plugins: [
    structureTool({
      structure: (S) =>
        S.list()
          .title('Content')
          .items([
            // Singleton for settings
            S.listItem()
              .title('Settings')
              .id('settings')
              .child(
                S.document()
                  .schemaType('settings')
                  .documentId('settings')
              ),
            // Singleton for homepage
            S.listItem()
              .title('Homepage')
              .id('homepage')
              .child(
                S.document()
                  .schemaType('homepage')
                  .documentId('homepage')
              ),
            // ... other document types
            ...S.documentTypeListItems()
              .filter((listItem) => !singletonTypes.has(listItem.getId()))
          ])
    })
  ]
})

2. Filter Templates - Hide from "Create new" menu

export default defineConfig({
  // ... other config
  schema: {
    types: [/* your schemas */],
    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 Note

You need to create the document instance first before adding it to the singletonTypes set. Otherwise, you won't have a way to create it through the UI.

Easier Alternative: Use a Plugin

If you want to skip the manual configuration, you can use the singleton-tools plugin which handles all of this automatically.

Your schema for something like company settings would look like a normal document schema:

export default {
  name: 'settings',
  title: 'Settings',
  type: 'document',
  fields: [
    {
      name: 'companyLogo',
      title: 'Company Logo',
      type: 'image'
    },
    {
      name: 'companyAddress',
      title: 'Company Address',
      type: 'text'
    }
  ]
}

The singleton configuration just controls how it appears in the Studio interface - as a single object rather than a list you can add to! You can find the full guide on setting up singleton documents in the Sanity documentation.

Show original thread
13 replies
A ‘singleton’ is what you’re looking for. This might help: https://www.sanity.io/docs/create-a-link-to-a-single-edit-page-in-your-main-document-type-list
Amazing! that was super quick too. Thank you
user J
- i am new to Sanity so still getting my head around things
No problem!
Hey
user J
so I've followed the instructions and seem to have it set up. However, the fields within the document are edit only and I can't understand why. Are you familiar with this situation and why that might be?
Can you share your schema?
Sure. here you go
hmm, schema looks okay at first glance. Try adding back in
create
in this line:
__experimental_actions: [/*'create',*/ 'update', /*'delete',*/ 'publish'],
Update that document, then comment it back out again. I think it’s because right now that document doesn’t exist
🤔
Cory’s suggestion gets at the likely cause; the document needs to exist before setting
__experimental_actions
in the schema.
user A
user J
that worked! thank you. That documentation might need to be tweaked then.
One thing though, as there is no title, is there a way to 'hardcode' the title in? looks a bit wierd remaining as 'untitled'
I wonder, is there a way of getting around having to enable and then disable 'creation'? I expect this will become problematic when new environments are created. I am also trying to set up a boilerplate sanity schame set up to use on many sites and this is something that could be easily forgotten and a niggly, seemingly hacky code change (and revert) that needs doing every time to establish the single document in the database.
I usually make a little node script that goes and creates all the necessary singleton documents.
Ah clever. sounds a bit too advanced for my level though. Is is an easy drop in script, or does it require some back end dev experience to set up?

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?