This is compatible with v4 and v3 of Sanity Studio.
This plugin adds convenience functions to reduce the overhead of creating singleton documents in the Sanity Studio.
In short, this does the following:
- Limits a singleton document's actions to Publish, Unpublish, and Discard Changes.
- Removes the ability to create new versions of the singleton document in both the global Create menu and Structure.
- Adds simple methods for customizing the way your singletons are listed in your Studio's Structure.
While Sanity Studio supports singleton documents through the Structure Builder API, this plugin eliminates the repetitive boilerplate and provides additional safeguards:
// Requires manual Structure Builder configuration for each singleton
export const structure = (S) =>
S.list()
.title('Content')
.items([
S.listItem()
.title('Site Settings')
.child(
S.document()
.schemaType('siteSettings')
.documentId('siteSettings')
),
// Must manually filter out singletons from main list
...S.documentTypeListItems().filter(listItem =>
!['siteSettings'].includes(listItem.getId()))
])
Issues:
- Repetitive boilerplate for each singleton
- No prevention of duplicate document creation
- Users can still create new versions via global Create menu
- Manual filtering required to prevent duplicates in document lists
With This Plugin:
// schema/singletonType.js/ts
import { defineType } from 'sanity';
export const mySingleton = defineType({
name: 'mySingleton',
title: 'My Singleton',
type: 'document',
options: {
singleton: true, // Identify this document as a singleton
},
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
},
...
],
});
// structure.js/ts
export const structure = (S, context) =>
S.list()
.items([
...singletonDocumentListItems({ S, context }), // Auto-generates all singletons
...filteredDocumentListItems({ S, context }) // Auto-filters singletons from main list
])
Benefits:
- ✅ Minimal configuration with
singleton: true
- ✅ Automatic action restrictions (no duplicate creation)
- ✅ Global Create menu integration
- ✅ Helper functions eliminate boilerplate
- ✅ Consistent singleton behavior across your studio
npm install sanity-plugin-singleton-management
This plugin is a modernized, actively maintained fork of sanity-plugin-singleton-tools
with identical API compatibility. Migration is straightforward:
-
Uninstall the old package:
npm uninstall sanity-plugin-singleton-tools
-
Install this package:
npm install sanity-plugin-singleton-management
-
Update your import statements:
// sanity.config.js - import { singletonTools } from 'sanity-plugin-singleton-tools' + import { singletonTools } from 'sanity-plugin-singleton-management' // structure.js - import { singletonDocumentListItem } from 'sanity-plugin-singleton-tools' + import { singletonDocumentListItem } from 'sanity-plugin-singleton-management'
That's it! No other code changes are required. Your existing schema configurations and structure customizations will work exactly the same.
- ✅ React 18/19 Support: Compatible with modern React versions
- ✅ Sanity v3/v4 Support: Works with both Sanity Studio versions
- ✅ Modern Tooling: ESM/CommonJS dual package, better TypeScript support
- ✅ Comprehensive Tests: 100% test coverage for reliability
- ✅ Active Maintenance: Regular updates and dependency management
- ✅ Node 18+ Support: Modern Node.js compatibility
//sanity.config.js
import { defineConfig } from "sanity";
import { singletonTools } from "sanity-plugin-singleton-management";
export default defineConfig({
//...
plugins: [singletonTools()],
});
//mySingleton.js
export const mySingleton = {
name: "mySingleton",
title: "My Singleton",
type: "document",
options: {
singleton: true, // Identify this document as a singleton
},
};
// structure.js
import {
singletonDocumentListItem,
singletonDocumentListItems,
filteredDocumentListItems,
} from "sanity-plugin-singleton-management";
import { PlugIcon } from "@sanity/icons";
export const structure = (S, context) =>
S.list()
.title("Sanity Love Content")
.items([
// Create a list item for each singleton document in your schema that links directly to a document view
...singletonDocumentListItems({ S, context }),
// Create a list item for a specific singleton
singletonDocumentListItem({
S,
context,
// Schema type
type: "mySingleton",
// Required for showing multiple singletons of the same schema type
title: "My Singleton",
// Required for showing multiple singletons of the same schema type
id: "mySingleton",
// Specify a custom icon
icon: PlugIcon,
}),
S.divider(),
// Filter singleton documents out of the default S.documentTypeListItems() to prevent them from being rendered as lists or as duplicates
...filteredDocumentListItems({ S, context }),
]);
Other reading (Sanity docs):
MIT © RD Pennell & RC Maples