Roles and Permissions
Understand how the starter applies role-based guardrails in Sanity Studio, what is enforced by default, and where to extend access controls safely.
Overview
The starter uses role-aware checks in Sanity Studio to reduce accidental changes to sensitive fields and internal tooling.
It does not attempt to replace Sanity's own dataset-level permission model. Instead, it adds implementation-level guardrails in schema fields and Studio structure so day-to-day editorial work stays safe.
Primary implementation touchpoints in the enterprise starter:
packages/sanity-toolkit/studio/constants/roles.tspackages/sanity-toolkit/studio/utilities/roles/index.tsapps/sanity/structure/index.tspackages/sanity-toolkit/studio/singletons/schema.tsapps/sanity/schema/types/singletons/configSeo.tspackages/sanity-toolkit/features/redirects/schema/defineRedirectFields.ts
What is enforced by default
Role names are centralised
ROLE provides canonical role names used by Studio-side checks:
administratordevelopereditorglobal-content-admin
These names must align with your Sanity project role configuration.
Access helper for privileged actions
isDeveloperOrAdmin(currentUser) returns true for:
developeradministratorglobal-content-admin
The helper is reused across structure and schema code so privilege checks are consistent.
Privileged-only UI in Studio structure
The desk structure only renders the Skeleton Key pane for developer/admin users. This keeps diagnostic or low-level content views away from standard editors.
Field-level write restrictions
Sensitive fields are marked readOnly (and in some cases hidden) for non-privileged users, for example:
- singleton search-support fields (
[Dev] Singleton Title) are hidden and read-only for non-admin/developer users - SEO
siteUrlis read-only for non-admin/developer users - redirect analytics-style
countis read-only for non-admin/developer users
This pattern protects operational fields while still allowing editors to manage content fields.
Why this model works for enterprise teams
- It is explicit in code, which makes audits and reviews easier.
- It narrows risky edits without blocking normal content production.
- It keeps role logic reusable instead of scattering one-off checks in many schemas.
- It complements, rather than duplicates, Sanity's organisation-level permissions.
What is not enforced by default
- There is no custom role matrix per document type in this repository by default.
- There is no mandatory publish-approval workflow gate wired into document actions by default.
- There is no tenant-specific permissions engine beyond Sanity's native access controls.
If you need stricter governance (for example, only specific roles can publish certain schemas), add those rules through document action wrappers and Sanity project roles together.
Implementation guidance
- Keep role names in sync with your Sanity project settings before shipping.
- Reuse
isDeveloperOrAdmin(or adjacent helpers) instead of duplicating role checks inline. - Restrict only the fields that are operationally sensitive; avoid over-restricting editorial content fields.
- Prefer schema-level
readOnly/hiddenfor UX-level safety and Sanity project permissions for hard access boundaries.
Extension point for stricter action permissions
The toolkit includes handleAccessToActions(...) in:
packages/sanity-toolkit/studio/actions/handleAccessToActions.ts
This helper can disable document actions for selected roles and optionally allow action access when a document reaches readyToPublish workflow metadata state.
In the current starter, this helper exists as an extension point and is not wired into apps/sanity/actions/index.ts by default.
Last updated: 27 Apr 2026, 14:59:48
Editorial Workflow
Follow the end-to-end editorial lifecycle in the starter, from document creation and localisation to review states and publication in Sanity Studio.
Scalability and Operational Headroom
Scale one codebase across multiple sites, languages, and content volumes through proxy-based tenancy, tag-scoped caching, and monorepo task orchestration.
