Studio

Handle intents in the Structure Tool

How the Structure Tool matches intents to panes, and how to declare intent handling on lists that don't match on their own.

Intents are Studio's internal routing mechanism. When a user clicks a search result, follows an Open in Studio link from Visual Editing, or uses a Create new button, Studio fires an intent (like edit or create) with parameters such as the document ID and type. The Structure Tool resolves that intent by finding the right pane in your structure.

This guide explains how Studio decides which pane handles an intent, and shows how to declare intent handling on lists that don't match on their own.

Prerequisites

How Studio matches an intent to a pane

Studio matches an intent to a pane in two independent ways. Either one is enough.

First, a pane can declare what it handles with canHandleIntent. Lists built with S.documentTypeList() and S.documentTypeListItem() get a default implementation that reads the schema types named in the list's filter and matches when the intent's type parameter is one of them. Any filter that names a type counts, such as _type == "post" && defined(publishedAt) — not only the default filter.

Second, the intent resolver checks the pane directly, whatever its canHandleIntent says. A documentList matches when its schema type equals the intent's type parameter and its filter is still exactly _type == $type.

Panes that match neither way need canHandleIntent to declare which intents they handle: a custom S.list(), or a documentList whose filter doesn't name a schema type.

Adding a custom .child() resolver to a documentTypeList clears the default canHandleIntent, because Studio can't guarantee the new child handles the intent. The list keeps matching through the second route anyway, since .child() changes neither the schema type nor the filter. Change the filter as well and both routes drop out, so you have to declare canHandleIntent yourself.

What .child() does change is what opens. The intent routes to a pane for the target document ID, and your resolver decides what that pane shows. If it returns a list instead of a document node, the document editor doesn't open, and canHandleIntent won't change that.

Common symptoms of missing intent handling

If a list in your structure matches neither way, and you notice any of these, missing canHandleIntent could be the cause:

  • Documents open in the wrong pane. The document opens as a bare editor instead of navigating to the correct location in your structure.
  • Open in Studio links from Visual Editing don't route correctly.
  • Search results land in the wrong place. Global search can bypass your custom structure entirely.
  • Create new buttons may not work as expected. Custom structures that replace documentTypeList can lose the built-in create intent handling. A documentTypeList that keeps its default filter and adds a .child() resolver has a different cause: the intent routes correctly, but the child resolver decides what opens.

When no pane in your structure matches, Studio opens the document in a fallback editor outside your structure. You can recognize it by the pane ID in the URL, which starts with __edit__.

Add intent handling

Add canHandleIntent to any list that matches neither way. The function receives the intent name and parameters, and returns true if the pane should handle the intent:

Custom lists need intent handling

For the full canHandleIntent signature and parameters, see the Structure Builder API Reference.

Next steps

Was this page helpful?