How to hide dashboard, menu items, and schema pages based on user role or email?

4 replies
Last updated: Nov 29, 2025
Btw, can I hide some dashboard, menu items, schema pages from users with a “editor” role or based on a e-mail, username?
AI Update

Yes, you can hide dashboard items, menu items, and schema pages from users based on their role or email! This is a powerful feature for customizing the Studio experience based on user permissions.

Key Approaches

1. Custom Roles with Content Resources

First, you'll want to set up custom roles (available on Enterprise plans) to control what content users can access. Custom roles use GROQ filters to define which documents users can see and edit.

2. Structure Builder Customization

You can customize what appears in the Studio using the Structure Builder API based on user context. The Structure Builder receives a context object that includes currentUser information:

import type {StructureResolver} from 'sanity/structure'

export const structure: StructureResolver = (S, context) => {
  const user = context?.currentUser
  const roles = user?.roles.map((r) => r.name)
  
  // Check if user has specific role
  const isEditor = roles?.includes('editor')
  
  return S.list()
    .id('root')
    .title('Content')
    .items([
      // Always show articles
      S.documentTypeListItem('article').title('Articles'),
      
      // Only show settings for non-editors
      ...(!isEditor ? [
        S.documentTypeListItem('settings').title('Settings')
      ] : [])
    ])
}

3. Accessing User Information

The currentUser object provides:

  • email: User's email address
  • id: User ID
  • name: User's name
  • roles: Array of role objects with name and title

You can also use the userHasRole() helper function:

import {userHasRole} from 'sanity'

if (userHasRole(currentUser, 'editor')) {
  // Hide certain items
}

4. Filtering by Email or Username

You can filter based on email directly:

const isSpecificUser = user?.email === 'editor@example.com'

5. New Document Options

You can also control which document types appear in the "Create" menu:

// In sanity.config.ts
export default defineConfig({
  document: {
    newDocumentOptions: (prev, {currentUser}) => {
      const roles = currentUser?.roles.map(r => r.name)
      
      // Remove certain types for editors
      if (roles?.includes('editor')) {
        return prev.filter(item => 
          !['settings', 'config'].includes(item.templateId)
        )
      }
      
      return prev
    }
  }
})

6. Conditional Plugin Configuration

You can even hide entire tools/plugins based on role:

plugins: [
  media(),
  {
    name: 'conditional-tools',
    tools: (prev, {currentUser}) =>
      userHasRole(currentUser, 'editor')
        ? prev.filter((tool) => tool.name !== 'media')
        : prev
  }
]

Important Notes

  • Roles are additive: If a user has multiple roles, they get the combined permissions
  • Security: UI hiding doesn't replace proper content permissions - always set up custom roles for actual access control
  • Dataset privacy: For restricted content, set datasets to private (public datasets bypass role restrictions)

Check out the Studio customizations lesson for detailed examples and the custom roles documentation for setting up proper permissions.

Show original thread
4 replies

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?