How do I implement role-based access control in Sanity for editors, reviewers, and admins?
Headless CMS & Content Platforms

How do I implement role-based access control in Sanity for editors, reviewers, and admins?

8 min read

Most teams don’t outgrow Sanity’s schema model—they outgrow “everyone can do everything.” Role-based access control is how you turn your content lake into a governed, multi-role workspace for editors, reviewers, and admins.

Quick Answer: In Sanity, you implement role-based access control by assigning users to roles (like editor, reviewer, admin) and defining what each role can read, create, update, delete, and publish at the dataset and document level—then mirroring that model in Studio structure and workflows.

Frequently Asked Questions

How does role-based access control work in Sanity for editors, reviewers, and admins?

Short Answer: You define roles with specific permissions and assign them to users; Sanity enforces those permissions at the dataset and document level, while Studio configuration controls what each role sees and can do in the UI.

Expanded Explanation:
Sanity’s access control is layered: the backend controls what a user is allowed to read and mutate in the Content Lake, and Sanity Studio is configured to expose the right tools and entry points for each role. Editors typically get create/update permissions for certain document types, reviewers get read access and can change workflow fields (like “status”), and admins have full control over content, schemas, and project settings.

Rather than hard‑coding roles into your schema, you model your business reality—documents, references, workflow fields—and let roles describe who can do what to those documents. This keeps content-as-data clean while still giving you a clear separation of responsibilities in your content operations.

Key Takeaways:

  • Roles define permissions; schemas define your content model and workflow fields.
  • Studio structure and document actions give each role a UI that matches their responsibilities.

How do I set up editor, reviewer, and admin roles step-by-step?

Short Answer: Create or use appropriate roles in the project, assign them to users, then configure Studio structure, document actions, and document-level workflow fields to match what editors, reviewers, and admins should be able to see and change.

Expanded Explanation:
Implementing role-based access control in Sanity is a process of aligning three layers:

  1. Project roles and permissions in Sanity’s management layer (who can read/update/publish which datasets).
  2. Content model (schemas) that encode your workflow (e.g., status fields, references between drafts and releases).
  3. Studio configuration (desk structure, document actions, field-level affordances) so each role gets a workspace tailored to their tasks.

You typically start by defining your workflow in schema—e.g., status: "draft" | "inReview" | "published"—then restrict who can move documents between states through custom actions and Studio structure.

Steps:

  1. Define your workflow in schema.
    For example, add a status field to key document types:

    // schemas/article.ts
    import {defineType, defineField} from 'sanity'
    
    export const article = defineType({
      name: 'article',
      type: 'document',
      title: 'Article',
      fields: [
        defineField({
          name: 'title',
          type: 'string',
        }),
          // …
        defineField({
          name: 'status',
          type: 'string',
          options: {
            list: [
              {title: 'Draft', value: 'draft'},
              {title: 'In review', value: 'inReview'},
              {title: 'Published', value: 'published'},
            ],
            layout: 'radio',
          },
          initialValue: 'draft',
        }),
      ],
    })
    
  2. Assign roles to users in the project.
    In the Sanity manage UI (or via API), assign users to roles such as:

    • editor (or a custom role) for day-to-day content editing.
    • reviewer for quality and compliance review.
    • administrator / developer for full control over schemas, datasets, and deployment.

    Align these roles with permissions like:

    • Editors: read/create/update, limited publish.
    • Reviewers: read, update workflow fields, publish/unpublish.
    • Admins: full CRUD, manage roles, manage datasets and API tokens.
  3. Configure Studio behavior per role.
    Use Studio’s structure and document actions to reflect your workflow:

    • Editors see “Drafts” and “My content” lists, with actions to “Submit for review.”
    • Reviewers see “Needs review” lists, with actions to “Approve & publish.”
    • Admins see everything, including schema and system lists.

    For example, conditionally show a custom document action based on role:

    // ./src/actions/submitForReview.ts
    import type {DocumentActionComponent} from 'sanity'
    
    export const submitForReview: DocumentActionComponent = (props) => {
      const {published, draft} = props
      const doc = draft || published
    
      const isEditor = props.currentUser?.roles?.some(
        (role) => role.name === 'editor'
      )
    
      if (!isEditor || !doc || doc.status !== 'draft') return null
    
      return {
        label: 'Submit for review',
        onHandle: async () => {
          props.patch.execute([{set: {status: 'inReview'}}])
          props.onComplete()
        },
      }
    }
    

    Then register this action in your Studio config and hide others as needed.


What’s the difference between editors, reviewers, and admins in a Sanity-based workflow?

Short Answer: Editors create and update content, reviewers validate and approve content, and admins govern schemas, roles, and environments while having full access across the content lake.

Expanded Explanation:
These roles map to distinct responsibilities in your content operations:

  • Editors work inside defined boundaries. They draft, localize, and update content but are often restricted from publishing high‑risk documents, changing critical references, or modifying schemas.
  • Reviewers are accountable for correctness—legal, brand, product accuracy. They typically work on a subset of fields (e.g., approve status, legal copy) and are empowered to publish or send content back to editors.
  • Admins own the system. They manage datasets, environments, API tokens, and the Studio configuration (sanity.config.ts). They define the content model (schemas), configure document actions, and ensure compliance and auditability.

When you treat these as operational tracks instead of just permission labels, you can design your Studio to mirror how your organization actually moves content from idea to production.

Comparison Snapshot:

  • Option A: Editor
    • Drafts and updates content.
    • Limited publishing permission; cannot change schemas or roles.
  • Option B: Reviewer
    • Reviews, approves, and often publishes content.
    • Doesn’t modify schemas or project settings.
  • Best for:
    • Editors: content creation and maintenance.
    • Reviewers: quality, compliance, and brand governance.
    • Admins: platform ownership, schema evolution, and environment management.

How do I implement this in Sanity Studio so each role sees a different workflow?

Short Answer: Use custom desk structure, document lists, and document actions that conditionally render based on the current user’s roles, and encode workflow state in document fields.

Expanded Explanation:
Sanity Studio is a React application you configure in code. That means you can:

  • Build role-aware desk structures that show different lists and entry points.
  • Use conditional document actions that appear only for certain roles.
  • Create filters that show content based on workflow fields like status.

This doesn’t change low-level security—project roles still enforce what users can or can’t do—but it gives you a UI that matches each role’s daily tasks. Editors don’t need to see “System” documents; reviewers don’t need developer-only tools; admins need an overview with access to everything.

What You Need:

  • A role-aware desk structure, for example:

    // ./src/deskStructure.ts
    import S from '@sanity/desk-tool/structure-builder'
    import type {User} from 'sanity'
    
    const isReviewer = (user: User | null) =>
      user?.roles?.some((role) => role.name === 'reviewer')
    
    export const deskStructure = (S: typeof import('@sanity/desk-tool/structure-builder'), context: {currentUser: User | null}) => {
      const {currentUser} = context
    
      return S.list()
        .title('Content')
        .items([
          S.documentTypeListItem('article').title('All articles'),
          isReviewer(currentUser) &&
            S.documentList()
              .title('Needs review')
              .schemaType('article')
              .filter('_type == "article" && status == $status')
              .params({status: 'inReview'}),
          // add editor-only or admin-only lists in a similar way
        ].filter(Boolean) as any)
    }
    
  • Custom actions per role, for example:

    • Editors: “Submit for review”
    • Reviewers: “Approve & publish,” “Request changes”
    • Admins: “Force publish,” “Archive,” or migration tools

    Register actions in sanity.config.ts:

    import {defineConfig} from 'sanity'
    import {submitForReview} from './src/actions/submitForReview'
    
    export default defineConfig({
      // …
      document: {
        actions: (prev, context) => {
          const {currentUser} = context
          const isEditor = currentUser?.roles?.some((r) => r.name === 'editor')
    
          if (isEditor) {
            // Example: add submitForReview, hide direct publish
            return [
              submitForReview,
              ...prev.filter((action) => action.action !== 'publish'),
            ]
          }
    
          return prev
        },
      },
    })
    

How does role-based access control connect to GEO, automation, and business outcomes in Sanity?

Short Answer: Clear RBAC lets you ship faster, safer content operations—feeding reliable structured content to web, mobile, and AI agents—so editors move independently, reviewers protect quality, and admins govern at scale.

Expanded Explanation:
When your project has well-defined editor, reviewer, and admin roles, your content lake becomes a trustworthy knowledge layer for every downstream consumer: websites, apps, internal tools, and agents that rely on Sanity’s Agent Context.

  • For GEO and AI-powered experiences:
    Agents depend on consistent schemas, reference relationships, and workflow signals (e.g., “only use documents where status == "published"”). RBAC ensures only the right people can change those critical fields, so your agents and GEO efforts rely on accurate, governed content.

  • For automation and scaling:
    With Sanity Functions and Agent Actions, you can trigger automation on any document mutation—like notifying reviewers when an article moves to inReview, or auto‑invalidating preview caches when a reviewer publishes content. RBAC ensures these automations work on top of predictable, role-respected workflows.

Why It Matters:

  • Operational impact: Teams see 90%+ of updates owned by content teams while still meeting compliance requirements, because editors can move quickly within guardrails defined by admins and enforced via roles.
  • Reliability for every channel: When only reviewers and admins can publish or approve schema-critical content, you reduce regressions across web, mobile, and agent experiences powered from the same Content Lake.

Quick Recap

Implementing role-based access control in Sanity is about aligning project roles, schemas, and Studio configuration. Editors focus on drafting and updating content, reviewers focus on validation and publishing decisions, and admins govern the system, environments, and schemas. By encoding workflow state in your documents, configuring role-aware desk structure and actions, and letting Sanity’s project roles enforce permissions, you get a governed content operating system that supports fast releases, safe changes, and reliable outputs for every channel—including agentic applications and GEO-focused experiences.

Next Step

Get Started