How to hide structure elements based on user role in Sanity v3.

3 replies
Last updated: Oct 14, 2023
Is there any way to hide structure elements depending on the user role?
For example I want to only show a certain list if the user is an administrator.

It seems this was possible in v2 (
https://www.sanity.io/schemas/desk-structure-with-custom-roles-332e8ada ) but I can't seem to figure out a way to do this in v3. Does anyone know if it's possible? Surely it should be right?
AI Update

Yes, this is absolutely possible in Sanity Studio v3! You can access the current user's information, including their roles, through the context object in your structure configuration.

In Studio v3, when you define your structure using the structure tool, you receive a context object that includes currentUser. Here's how you can use it:

// sanity.config.ts
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'

export default defineConfig({
  // ... other config
  plugins: [
    structureTool({
      structure: (S, context) => {
        const {currentUser} = context
        
        // Check if user has admin role
        const isAdmin = currentUser?.roles.some(
          role => role.name === 'administrator'
        )
        
        return S.list()
          .title('Content')
          .items([
            S.documentTypeListItem('post').title('Posts'),
            // Only show this item to administrators
            ...(isAdmin ? [
              S.documentTypeListItem('settings').title('Settings')
            ] : []),
            // ... other items
          ])
      }
    })
  ]
})

The currentUser.roles array contains role objects with properties like name, title, and other role information. Common built-in role names include:

  • administrator
  • editor
  • viewer
  • developer
  • contributor

You can also hide specific tools (like the Vision plugin or Media Library) based on user roles by conditionally including them in your plugins array:

plugins: [
  structureTool({/* ... */}),
  // Only include Vision plugin for administrators
  ...(currentUser?.roles.some(r => r.name === 'administrator') 
    ? [visionTool()] 
    : [])
]

I completely agree the documentation could be clearer on this - there's an example in the migration cheat sheet, but you'd pretty much already have to know where it is to find it. The pattern is the same as v2, just with the updated import paths and configuration structure for v3.

For more advanced access control scenarios (like restricting access to specific documents or fields based on roles), you might want to look into Custom Roles, which are available on Enterprise plans and allow you to define granular permissions using GROQ filters to control who can read, update, create, or publish specific content resources.

Turns out this IS possible to do, but absolutely nowhere in the documentation. Just in blog posts for v2.
To do this, you can pull the current user off the context object that is exposed alongside the structure builder. This will let you check the roles of users before returning a list.

This really should be in the documentation as this has been giving me a headache for about 2 hours
There’s an example here but you’d pretty much already have to know where it is to find it.
Coming back to this! How would you render certain plugins based on a role (such as media and vision plugin)?

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?