Tools common patterns
Common code snippets to help customize the tools in your studio.
Tools are a powerful way to add additional functionality to Sanity Studio. Here are some ways of customizing how tools work in your studio.
Order tools in the navigation bar
Sometimes you need to change the order that tools appear in the navigation bar. Tools added by plugins in the plugins array come first, followed by tools added directly in the tools array. A plugin or your own config can override the display order by supplying a studio.components.toolMenu component and passing a reordered tools array to renderDefault. The first tool in the resolved array is the one that opens when your studio loads.
In this example, the toolMenu component reorders the resolved tools so a specific tool sits first in the navigation bar, regardless of registration order.
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
import {schemaTypes} from './schemaTypes'
export default defineConfig({
name: 'default',
title: 'example',
projectId: 'YOUR_PROJECT_ID',
dataset: 'YOUR_DATASET',
studio: {
components: {
toolMenu: (props) => {
const {tools, renderDefault} = props
const structureTool = tools.find(({name}) => name === 'structure')
const otherTools = tools.filter(({name}) => name !== 'structure')
if (!structureTool) {
return renderDefault(props)
}
return props.renderDefault({
...props,
tools: [structureTool, ...otherTools],
})
},
},
},
plugins: [structureTool()],
tools: [myCustomTool, myOtherCustomTool],
schema: {
types: schemaTypes,
},
})Configure the default tool
Sometimes you need to order the tools in the navigation bar, but you want a specific tool to open when your studio loads. In this case, use the tools property in the configuration to sort the tools array.
In this example, the (prev, context) callback pattern sorts the array and places the Vision Tool first.
import {defineConfig} from 'sanity'
export default defineConfig({
name: 'default',
title: 'example',
projectId: 'YOUR_PROJECT_ID',
dataset: 'YOUR_DATASET',
// ... rest of config
tools: (prev, context) => {
return prev.sort((a, b) => {
if (a.name === 'vision') {
return -1 // Moves 'vision' tool to the top of the list
}
return 1
})
}
})This changes both the navigation bar order and the tool that opens by default. To control the two independently, keep the tools array in the order you want the default tool resolved from, and reorder the menu with a studio.components.toolMenu component. For example, combine this approach with a custom toolMenu component so the Vision Tool opens when you visit your studio.
Display a tool only in development environments
Sometimes you need to display a tool only in development environments. Use process.env.NODE_ENV !== 'production', which is true when your studio runs on the local development server and false in a studio you have built or deployed. In this example, your studio displays the Vision and Structure tools in development, but only the Structure Tool in other environments. When only one tool remains, the studio hides the tool menu entirely, so no tool switcher appears in the navigation bar.
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
import {visionTool} from '@sanity/vision'
const isDev = process.env.NODE_ENV !== 'production'
export default defineConfig({
// ...
plugins: isDev
? [structureTool(), visionTool()]
: [structureTool()],
})Conditionally render tools based on role
Sometimes you want to display tools for specific user roles. There are a few ways to do this. Filtering the whole tools array is the recommended approach when more than one tool is role-gated, because the rules for every tool live in one place. In this example, administrators have access to all tools while all other users can only use the Structure Tool. When only one tool remains, the studio hides the tool menu entirely, so no tool switcher appears in the navigation bar.
import {defineConfig, userHasRole} from 'sanity'
import {structureTool} from 'sanity/structure'
import {visionTool} from '@sanity/vision'
// define an array of tools
const userTools = ['structure']
export default defineConfig({
name: 'default',
title: 'example',
projectId: 'YOUR_PROJECT_ID',
dataset: 'YOUR_DATASET',
// This studio includes structure, vision, and any plan-specific tools
plugins: [structureTool(), visionTool()],
tools: (prev, context) => {
// Retrieve the current user from the context
const {currentUser} = context
// Check if the current user is not an admin
if (!userHasRole(currentUser, 'administrator')) {
// return an array that only includes tools in the userTools array
return prev.filter((tool) => userTools.includes(tool.name))
}
// Otherwise, return all tools
return [...prev]
},
// ... rest of config
})To adjust a single tool instead of filtering the whole array, this example limits the Vision Tool to only administrators.
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
import {visionTool} from '@sanity/vision'
export default defineConfig({
name: 'default',
title: 'example',
projectId: 'YOUR_PROJECT_ID',
dataset: 'YOUR_DATASET',
plugins: [structureTool(), visionTool()],
tools: (prev, context) => {
// Retrieve the current user from the context
const {currentUser} = context
const isAdmin = currentUser?.roles.some((role) => role.name === 'administrator')
// If the user has the administrator role, return all tools.
// If the user does not have the administrator role, filter out the vision tool.
return isAdmin ? prev : prev.filter((tool) => tool.name !== 'vision')
},
// ... rest of config
})