Difference between S.editor() and S.document() and how to disable deletion and unpublishing of certain document types in Sanity.io
Looking at your code, I can see you're working with Sanity V2 (using the old part: imports). The good news is that your approach to filtering document actions is actually the standard way to handle this!
S.editor() vs S.document()
S.editor() is simply a deprecated alias for S.document() - they do the exact same thing. In older versions of Sanity, S.editor() was used, but it was renamed to S.document() for clarity. You should use S.document() in your code, though S.editor() will still work as it points to the same method.
Both methods create a document view in the Structure Builder. The difference you're looking for is actually between list items (S.listItem()) and document views (S.document()), where list items are the navigation elements and document views are what displays when you open a document.
Preventing Deletion/Unpublish for Singleton Documents
Your current approach with custom document actions is actually the correct and cleanest way to prevent deletion and unpublishing. There isn't a built-in property in the Structure Builder's S.listItem() or S.document() that disables these actions - you need to filter the document actions as you're doing.
However, here's a slightly cleaner version for V2:
import defaultResolve, {
UnpublishAction,
DuplicateAction,
DeleteAction,
} from "part:@sanity/base/document-actions";
const SINGLETON_TYPES = [
"navigation",
"general",
"featured",
"promo",
"cookie",
"friends"
];
const documentActions = (props) => {
if (SINGLETON_TYPES.includes(props.type)) {
return defaultResolve(props).filter(
(action) => ![UnpublishAction, DuplicateAction, DeleteAction].includes(action)
);
}
return defaultResolve(props);
};
export default documentActions;Hiding from "Create New Document" Menu
To prevent these singleton documents from appearing in the "Create New Document" menu, you can also filter the templates in your sanity.json:
{
"parts": [
{
"name": "part:@sanity/base/new-document-structure",
"path": "./newDocumentStructure.js"
}
]
}Then create newDocumentStructure.js:
import S from '@sanity/base/structure-builder'
const SINGLETON_TYPES = ['navigation', 'general', 'featured', 'promo', 'cookie', 'friends'];
export default [
...S.defaultInitialValueTemplateItems().filter(
(template) => !SINGLETON_TYPES.includes(template.spec.id)
)
]Modern Approach (Studio V3+)
If you ever upgrade to Studio V3, the approach is similar but with updated imports. The singleton document guide shows the modern implementation, which uses the same filtering concept but with the newer API structure in sanity.config.js:
// For V3+
schema: {
templates: (templates) =>
templates.filter(({ schemaType }) => !singletonTypes.has(schemaType))
},
document: {
actions: (input, context) =>
singletonTypes.has(context.schemaType)
? input.filter(({ action }) => action && singletonActions.has(action))
: input
}Your current solution is solid - sometimes the "ugly" way is just the way it needs to be done! π The document actions approach is the standard pattern for controlling which actions are available for different document types.
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.