How to hide dashboard, menu items, and schema pages based on user role or email?
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 addressid: User IDname: User's nameroles: Array of role objects withnameandtitle
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 thread4 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.