
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeThis is a classic issue with custom desk structures in Sanity Studio! When you create a new document and the Studio "loses track" of where you are (jumping back to the root or wrong pane), it's almost always because your custom structure is missing the canHandleIntent method on your list items.
When you create a new document, Sanity Studio tries to figure out which pane should handle that intent (like "create" or "edit"). Without canHandleIntent defined, the Studio can't match the new document to your custom filtered list items, so it falls back to opening the document in an unexpected location—usually the root pane.
You need to add the canHandleIntent method to your custom listItem() definitions. This tells the Studio "yes, this pane can handle documents of this type with these characteristics."
Here's an example for a multilingual structure:
S.listItem()
.title('English Content')
.id('english-content')
.child(
S.documentList()
.title('English Content')
.filter('_type == $type && language == $language')
.params({ type: 'page', language: 'en' })
)
.canHandleIntent((intentName, params) => {
// Handle create and edit intents for documents with English language
return (
(intentName === 'create' || intentName === 'edit') &&
params.type === 'page' &&
params.language === 'en'
)
})For multilingual setups specifically, your canHandleIntent should check:
'create' or 'edit'params.type)params.language if you're setting it via initial value templates)If you're using language folders, each language-specific list item needs its own canHandleIntent that checks for matching language values.
Here's a more complete pattern for a language-based structure:
const languageList = (lang: string) =>
S.listItem()
.title(`${lang.toUpperCase()} Content`)
.id(`${lang}-content`)
.child(
S.documentList()
.title(`${lang.toUpperCase()} Content`)
.filter('_type in $types && language == $lang')
.params({ types: ['page', 'post'], lang })
)
.canHandleIntent((intentName, params) => {
return (
['create', 'edit'].includes(intentName) &&
params.language === lang
)
})
export const structure: StructureResolver = (S) =>
S.list()
.title('Content')
.items([
languageList('en'),
languageList('es'),
languageList('fr'),
// ...other language lists
])canHandleIntent match what's actually on your documents or what's being passed through initial value templatesid() on your list items is also important—make sure each has a unique, descriptive IDIf it's still not working after adding canHandleIntent:
language)params object inside canHandleIntent to see what's actually being passedlanguage field that matches what you're filtering onThe Structure Builder API reference has more details on all available methods. The canHandleIntent method is documented under both List and ComponentView sections, though examples can be tricky to find since it's often overlooked until you hit this exact issue!
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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store