Structure Builder API Reference
Overview of different methods in the Structure Builder API
This is the complete reference documentation for Structure Builder. This API lets you configure how the Sanity Studio's Structure tool organizes lists, documents, views, menus, and initial value templates.
The Structure Builder API is designed as a collection of methods that can be chained and passed in as arguments/parameters. To learn about the central concepts of Structure Builder, go to the introduction article and dive deeper into the API in the TypeScript reference documentation.
Protip
Looking for quick examples of common use cases? See the Structure Builder cheat sheet.
You can build custom structures by passing the structure to the structure tool configuration. To do this, define the structure resolver function, which receives the Structure Builder instance, by convention referred to as S
, as its first argument, and a context object as its second.
// sanity.config.js
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
import {schemaTypes} from './schema'
export default defineConfig({
name: 'default',
title: 'My Cool Project',
projectId: 'my-project-id',
dataset: 'production',
plugins: [
structureTool({
structure: (S, context) => {
console.log(context) // returns { currentUser, dataset, projectId, schema, getClient, documentStore }
return S.documentTypeList('post')
},
})
],
schema: schemaTypes
})
Where you define your structure is up to you - you could define it inline (as in the above example), or you could place it in a separate file and import/use it in your structure tool config:
// src/structure.js
export const structure = (S) => S.documentTypeList('post')
// sanity.config.ts
import { defineConfig } from 'sanity'
import { structureTool } from 'sanity/structure'
import { structure } from './src/deskStructure'
export default defineConfig({
// ...
plugins: [
structureTool({
structure
})
]
})
In the Structure Builder API, you'll find “convenience methods.” We recommend using these unless you want more fine-grained control.
datasetstring
Name of the current dataset
projectIdstring
Unique ID for the project
schemaobject | Schema
The schema registry of your project. Use `schema.get("schemaTypeName") to retrieve any schema by name.
currentUserobject | CurrentUser
An object with info about the currently logged in user.
getClientfunction | SanityClient
Callback function that returns a configured client
documentStoreobject
These methods define how lists and list items appear in the collapsible panes within the Studio’s structure tool. There are methods you can consider as “primitives” and methods that take a document schema type and automatically configure menus, initial value templates, and similar from the schema configuration.
Protip
You should generally opt for documentTypeList
and documentList
when you can since these give you good defaults and sets up a lot of things automatically for you.
list():List
A primitive for defining the list content of the collapsible pane, including its title and representation in the URL bar. Typically used when you want to group different list items within a pane.
Protip
Are you getting the error Structure node id cannot contain character ...
? This is typically caused when the title
contains a character that is not in the domain of (or cannot be automatically converted to the domain of) web-safe characters.
The solution is to explicitly specify an id
that includes only web-safe characters.
id(id): List
Set the id for the list.
Parameters
idstring
Identifier for the list used to reflect the current structure state in the studio’s URL. Derived automatically from
.title()
if not explicitly defined.
title(title): List
Set the title for the list.
Parameters
titlestring
The title to use for the list
items(items): List
Set the list items to display.
You would typically use a method that returns an array of list items, such as
documentTypeListItems
, or list item methods inserted into their own array, such aslistItem
anddocumentListItem
.Parameters
itemsarray
An array of list items.
showIcons(showIcons): List
Set whether or not to show the icons of the list items.
Parameters
showIconsboolean
Hides the list items icons if set to
false.
initialValueTemplates(templateItems): List
Sets which initial value templates should be available for this pane (which items appear when using "new document" on the pane).
Use
S.initialValueTemplateItem(templateId, parameters)
to get a reference to a template. By passing an object of parameters, you can contextualize the template for the specific pane. See the initial value template documentation for more information.Parameters
templateItemsInitialValueTemplateItem[]
Array of initial value template items.
menuItemsGroups(groups): List
Defines which groups of menu items should be available for the pane. This also defines the order of the groups.
You can either build these groups by using the builder method:
[S.menuItemGroup().id('some-id').title('Some title')]
or by passing an array of objects containing id and title properties:
[{id: 'some-id', title: 'Some title'}]
Parameters
groupsMenuItemGroup[]
Array of menu item groups to use.
menuItems(menuItems): List
Sets the list of menu items to appear in the pane menu.
Parameters
menuItemsMenuItem[]
Array of menu items to use. Use the menu item builder method
S.menuItem()
to build these.
defaultLayout(layout): List
Sets the default layout for this list. Currently the only supported layouts are
default
anddetail
.Parameters
layoutstring
Either
default
ordetail
.
child(child): List
Sets which structure node to use as the child of this list, when an item in the list is selected.
Can either be a structure node (any list, document, component etc) or a child resolver - a function that either syncronously or asyncronously resolves to a structure node.
Read more about child resolvers in the conceptual guide for the structure builder.
Parameters
childnode | function
canHandleIntent(intentChecker): List
Sets the method used to determined whether or not the pane can handle an intent of a certain type.
The intent checker receives three arguments:
intentName
,params
andcontext
. It should return a boolean indicating whether or not it can handle the intent.intentName
is generallycreate
oredit
.params
usually containsid
andtype
, representing the document ID and schema type to be created. Often it will also havetemplate
, a string representing the ID of an initial value template.context
is an object containingpane
andindex
Parameters
intentCheckerfunction
Intent checker function
getCanHandleIntent(): function
Returns the configured intent checker
getChild(): node | function
Returns the configured child or child resolver for this pane
getDefaultLayout(): string
Returns the defined default layout for this pane (if any)
getId(): string
Returns the configured ID for this pane, if any
getInitialValueTemplates(): InitialValueTemplateItem[]
Returns the list of configured initial value templates, if any
getItems(): node[]
Returns the list of configured list items, if any
getMenuItemGroups(): MenuItemGroup[]
Returns an array of the configured menu item groups, if any
getMenuItems(): MenuItem[]
Returns an array of the configured menu items, if any
getShowIcons(): boolean
Returns whether or not the pane is configured to show icons for the list items
getTitle(): string
Returns the configured title for the pane, if any
documentTypeList(schemaType):DocumentList
Convenience method for documentList()
. Returns a list node for the specified document type with its configuration for list items, menus, initial value templates, and views.
REQUIREDschemaTypestring
The schema type name of an existing document type that's defined in the Studio’s schema file.
See the methods summary for documentList
// src/structure.js (.ts)
// Exports a list of documents with the schema type “post”
export const structure = (S) => S.documentTypeList('post')
documentList():DocumentList
A variant of the list type is made specifically for displaying a list of documents. It lets you define which documents to list by using a GROQ filter expression (filter
) plus optional parameters (params
). Note that this list type does not have an items()
method - if you want to use specific list items, use the list()
method instead.
filter(filter): DocumentList
Filters the document list based on a GROQ filter expression.
Parameters
filterstring
GROQ-filter used to determine which documents to display. Does not support joins, since they operate on individual documents, and will ignore order-clauses and projections. See realtime updates
params(params): DocumentList
Sets the parameters to use when executing the query specified by the provided GROQ-filter
Parameters
paramsobject
An object of key/value pairs. Keys should not include the
$
prefix used in the filter.
apiVersion(apiVersion): DocumentList
Sets the API version to use for the given filter. Available since studio version v2.20.0.
Parameters
apiVersionstring
API version to use, eg
v2021-06-07
schemaType(schemaType): DocumentList
Sets the schema type of the documents expected to be in the list. This helps provide context for the tooling, but is not strictly required. Set this if you are expecting a single document type to be returned.
Parameters
schemaTypestring
defaultOrdering(orderings): DocumentList
Sets the default ordering for this document list:
documentList.defaultOrdering([{field: 'priority', direction: 'desc'}])
Parameters
orderingsSortItem[]
getFilter(): string
Returns the configured GROQ-filter for this list, if any
getParams(): object
Returns the configured parameters for the GROQ-filter, if any
getApiVersion(): string
Returns the configured API version for this list, if any
getSchemaType(): string
Returns the configured schema type for this pane, if any
getDefaultOrdering(): SortItem[]
Returns the configured default ordering for this document list, if any
// ./structure.js (.ts)
export const structure = (S) =>
S.list()
.title('Content')
.items([
S.listItem()
.title('Future projects')
.schemaType('sampleProject')
.child(
S.documentList()
.title('Future projects')
.filter('_type == "sampleProject" && publishedAt > now()')
)
])
Gotcha
Selecting a custom sort order in the Studio will override defaultOrdering
and retain that custom sort order in local storage. If your defaultOrdering
configuration doesn't appear to be working, try clearing your local storage or opening the Studio in a different browser.
// src/structure.js
export const structure = (S) => S.documentTypeList('sampleProject')
S.list()
.title('Content')
.items([
S.listItem('category')
.title('Projects by category')
.child(
S.documentList()
.title('Projects by category')
.schemaType('sampleProject') // Because we want menu items for “sampleProjects”
.filter('_type == "category"')
.child(id => // Returns the id for the selected category document
S.documentList()
.title('Projects by category')
.schemaType('sampleProject')
.filter('_type == "sampleProject" && $id in categories[]._ref')
.params({id}) // use the id in the filter to return sampleProjects that has a reference to the category
)
)
])
export const structure = (S) =>
S.list()
.title('Content')
.items([
/* list item(s) goes here */
])
listItem():ListItem
A primitive for defining a list item within a list in a collapsible pane. Usually used within the array of S.list().items([/* here */])
.
By using the child
method on the item, you can control what opens in the next pane when you interact with a listItem
. If not defined, it will use the parents' child resolver to determine the next pane.
id(id): ListItem
Sets the ID for this list item.
Setting an ID is highly recommended, but if no ID is provided it will be inferred from the title of the list item.
Parameters
idstring
ID of this list item. If you are intending to open a document, this should generally be a document ID.
title(title): ListItem
Set the title of the list item.
Parameters
titlestring
Title of the list item
icon(icon): ListItem
Set an icon for the list item.
Parameters
iconfunction
React component to use as icon.
child(child): ListItem
Sets the child that should be rendered if this item is selected. If you have many list items that should resolve to the same type of child, you should usually set the child resolver on the parent (usually a list) and use the ID to resolve the correct child.
Parameters
childnode | function
Either a child node (list, document, component etc) or a child resolver function that returns a structure node.
schemaType(schemaType): ListItem
Sets the schema type of this list item, if any. Only used if the list item represents a document.
Parameters
schemaTypestring
Schema type name
showIcon(showIcon): ListItem
Decide whether or not to show the icon for the list item.
Parameters
showIconboolean
getId(): string
Get the id of the list item, if any
getTitle(): string
Gets the title of the list item, if defined
getChild(): node | function
Get the child or child resolver of the list item, if defined
getSchemaType(): string
Gets the schema type for the list item, if defined
getShowIcon(): boolean
Gets whether or not the icon is shown.
documentListItem():DocumentListItem
Convenience method for returning a list item representing a document.
Prefer this over a regular listItem when manually building a list of items representing documents.
Shares the same methods as listItem
.
documentTypeListItem(schemaType):ListItem
Convenience method for returning a list item representing a document type. In other words, if you want a list item that opens a list of documents of a specific type when clicked, use this. It will automatically configure the title, icon, schema type, and similar.
schemaTypestring
Name of the schema type.
documentTypeListItems():ListItem[]
Convenience method. Returns an array of list items for all defined document types in your schema, and configure them with the correct titles, icons, initial value templates and similar.
export const structure = (S) =>
S.list()
.title('Content')
.items(
// List all document types except "siteSettings"
S.documentTypeListItems().filter(
item => item.getId() !== 'siteSettings'
)
)
divider():
Inserts a visual divider in a list.
//sanity.config.js
import {structure} from './structure'
export default defineConfig({
...
plugins: [
structureTool({
structure
}),
],
schema: schemaTypes
})
// ./structure.js (.ts)
export const structure = (S) =>
S.list()
.title('Content')
.items([
// Make a singleton of the document with ID “siteSettings”
S.documentListItem()
.id('siteSettings')
.schemaType('siteSettings'),
// Add a visual divider
S.divider(),
// Add the rest of the document types, but filter out the siteSettings type defined above
...S.documentTypeListItems().filter(
item => item.getId() !== 'siteSettings'
)
])
The document node type represents (as the title implies) a document. Often, it is referred to as "the editor node" since it's common for it to render a form allowing you to edit the document in question. However, it can also render other "views" of the document, which is why it has a more generic name.
The following methods let you configure what happens when you open a document. If no views are specified for a document node, it will return the default form view.
document():Document
A primitive for defining a document node.
id(id): Document
Set the id for the document node. Usually picking something like document or documentView is enough to differentiate it. Alternatively, you can use the document ID.
Parameters
idstring
Identifier for the document node used to reflect the current structure state in the studio’s URL.
title(title): Document
Set the title for the document. Leave blank to use the document title.
Parameters
titlestring
The title to use for the document
documentId(documentId): Document
Sets the document ID this document node represents
Parameters
documentIdstring
Document ID to use for this node
schemaType(schemaType): Document
Sets the schema type for this document
Parameters
schemaTypestring
The schema type name
initialValueTemplate(templateId, parameters): Document
Sets which initial value template should be used for this document (if any).
Parameters
templateIdstring
ID of the initial value template to use
parametersobject
Object of key-value pairs to be sent to the initial value template
views(views): Document
Defines which views should be rendered for this document. If not defined, it will use the default form view as the only view.
Currently, there are two view types: form and component.
The
S.form
method renders the form for a given document, allowing it to be edited.A component renders a custom React component. See the document node views documentation for example usage.
Parameters
viewsView[]
Array of views to use for this document node
child(child): Document
Sets which structure node to use as the child of this document, in the case where a view allows navigating to one.
Can either be a structure node (any list, document, component etc) or a child resolver - a function that either syncronously or asyncronously resolves to a structure node.
Read more about child resolvers in the conceptual guide for the structure builder.
Parameters
childnode | function
getId(): string
Returns the configured ID for this pane, if any
getTitle(): string
Returns the configured title for the pane, if any
getDocumentId(): string
Returns the configured document ID for this document node
getSchemaType(): string
Returns the configured schema type for this editor, if any
getInitialValuesTemplate(): string
Returns the configured initial value template ID, if any
getInitialValueTemplateParameters(): object
Returns the configured parameters for the initial value template, if any
getViews(): View[]
Returns an array of the configured views, if any
getChild(): node | function
Returns the configured child or child resolver for this pane
documentWithInitialValueTemplate(templateId, parameters):Document
Convenience method for building a document node with a specific initial value template and set of parameters. Automatically configures the document with the correct schema type.
Returns a document node and as such, has the same builder methods as document().
Many of the nodes in the structure builder (such as the document type list) automatically render a document node as a child if none is provided. While you can take full control of every node in the structure, this is sometimes a bit tedious if you usually return the same document node for every document or schema type.
The structure definition allows for defining a function which is called when the "default" should be resolved.
Gotcha
Note that this is not a function exposed on the Structure Builder API itself - rather, it is a function you declare and export for the Structure Builder to use as a fallback.
While the structure definition you provide is exported as the default export, you can also export a function named getDefaultDocumentNode that will be called in these situations:
getDefaultDocumentNode(options):Document
Export a function named getDefaultDocumentNode
that returns an S.document()
node to set the default configuration for document nodes (also often referred to as an "editor node" since it often contains the form view used to edit a document).
optionsobject
Object of contextual information that can be used to determine which properties the document node should have. Properties:
schemaType
- The value of a document’s_type
.documentId
- The ID of the document.
// sanity.config.ts (.js)
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'
import {structure, defaultDocumentNode} from './structure'
import { schemaTypes } from './schema'
export default defineConfig({
name: 'default',
title: 'My Cool Project',
projectId: 'my-project-id',
dataset: 'production',
plugins: [
structureTool({
structure,
defaultDocumentNode,
}),
],
schema: schemaTypes
})
// ./structure.js (.ts)
import { WebPreview, JsonView } from './previews'
export const structure = (S, context) =>
S.list()
.title('Content')
.items([
S.listItem()
.title('Settings')
.child(
S.document()
.schemaType('siteSettings')
.documentId('siteSettings')
),
...S.documentTypeListItems()
])
export const getDefaultDocumentNode = (S, {schemaType}) => {
// Conditionally return a different configuration based on the schema type
if (schemaType === "post") {
return S.document().views([
S.view.form(),
S.view.component(WebPreview).title('Web')
])
}
return S.document().views([
S.view.form(),
S.view.component(JsonView).title('JSON')
])
}
export default S.defaults()
Within a document pane, there can be one or more views. If there are more than one view node, they will appear as tabs. The views can be built using methods exposed on S.view
- eg S.view.form()
form():FormView
The form method returns the default form-based editor for the specified document type.
id(id): FormView
ID for the view, used for the URL
Parameters
idstring
ID of the view
title(title): FormView
Sets the title of the view. Appears when there are more than a single view for a document node.
Parameters
titlestring
The title for the component.
icon(icon): FormView
Sets an icon for the views tab
Parameters
iconfunction
React component to use as icon
getId(): string
Returns the ID of the view, if any
getTitle(): string
Returns the title of the view, if any
getIcon(): function
Returns the defined icon for this view, if any
S.view.form()
component(reactComponent):ComponentView
The component
method takes a React component and renders it into the document view. It's most often used for showing the values of a document in alternative ways to the default document form.
id(id): ComponentView
ID for the view, used for the URL
Parameters
idstring
ID of the view
title(title): ComponentView
Sets the title of the view. Appears when there are more than a single view for a document node.
Parameters
titlestring
The title for the component.
canHandleIntent(intentChecker): ComponentView
Sets the method used to determined whether or not the pane can handle an intent of a certain type. This method is especially useful for routing to custom components from global search results or other links.
The intent checker receives three arguments:
intentName
,params
andcontext
. It should return a boolean indicating whether or not it can handle the intent.intentName
is generallycreate
oredit
.params
usually containsid
andtype
, representing the document ID and schema type to be created. Often it will also havetemplate
, a string representing the ID of an initial value template.context
is an object containingpane
andindex
Parameters
intentCheckerfunction
Intent checker function
component(component): ComponentView
Sets the React component
Parameters
componentfunction | Component
The React component to render. The component is rendered with the following props:
document
published
The published values of the document. Returnsnull
if the document isn't published.draft
The values from the draft version of the document. Returnsnull
if there isn't a draft, that is, no changes made since last publish, or if the document is in its initial state.historical
The values for the selected document revision in the history view.displayed
The values for the currently selected document state, in this order of presedence:initial
,historical
,draft
,published
.
documentId
- The ID of the documentschemaType
- The schema type of the document
icon(icon): Component
Sets an icon for the views tab
Parameters
iconfunction
React component to use as icon
options(options): ComponentView
Sets additional user-defined options that will be passed to the React component as the
options
property.Parameters
optionsobject
Arbitrary key-value pairs of options for the React component
getId(): string
Returns the ID of the view, if any
getTitle(): string
Returns the title of the view, if any
getComponent(): function | Component
Returns the defined React component to use for the view, if any
getIcon(): function
Returns the defined icon for this view, if any
getOptions(): object
Returns the user-defined options for this view, if any
export const structure = (S) =>
S.documentTypeList('sampleProject')
.child(id =>
S.document()
.schemaType('sampleProject')
.documentId(id)
.views([
// The default form for editing a document
S.view.form(),
// Render the current selected document’s values as JSON
S.view.component(({document}) => (
<pre>{JSON.stringify(document.displayed, null, 2)}</pre>
)).title('View JSON')
])
)
Each pane may have a menu in its upper right corner. This is where you usually find ordering options and affordances for adding new documents. Menus can also hold initial value templates. The convenience list methods will automatically set up default menus for you (some of these may also require that you add schemaType()
).
menuItem():MenuItem
title(title): MenuItem
Sets the title for the menu item.
Parameters
titlestring
Title of the menu item
icon(icon): MenuItem
Sets the icon for the menu item.
Parameters
iconfunction
React component to use as the icon
action(action): MenuItem
Sets the action that should be performed when the menu item is selected. Can either be a function or a string.
If specifying a function, that function will be called with any configured
params
as the first argument when the item is clicked.If specifying a string, the menu will attempt to look for an object named
actionHandlers
on the React pane component holding the menu, and find a method with a matching name there. The function will be called with any configuredparams
as the first argument when the item is clicked.Parameters
actionstring | function
params(params): MenuItem
Sets an arbitrary object of parameters to pass to the action handler defined by
action()
, when clicked.Parameters
paramsobject
Arbitrary set of key-value parameters for the action
intent(intent): MenuItem
Sets an intent that should be performed when clicking this menu item.
An intent is an object with a
type
key with either the valuecreate
oredit
, and an optional set of parameters specified asparams
.For the
edit
intent, thetype
andid
properties are required (document type name and document ID, respectively):{type: 'edit', params: {id: 'documentID', type: 'person'}}
For the
create
intent, specifying atype
is required. If you want to use a specific Initial Value Template, you can specify atemplate
parameter with the ID of the template you want to use:{type: 'create', params: {type: 'person', template: 'book-author'}}
If you want to pass arbitrary parameters to the initial value template, you can use the array form of specifying parameters, where the first element of the array defines the actual intent parameters, while the second element defines the arbitrary template parameters:
{type: 'create', params: [{type: 'person', template: 'book-author'}, {some: 'template-param'}]}
Note that
intent
andaction
are mutually exclusive.Parameters
intentIntent
showAsAction(showAsAction): MenuItem
Sets whether or not the menu item should be displayed as an action instead of being part of the dropdown menu.
Actions appear next to the pane title and must be given an icon, since they have no room for a title unless hovered.
Parameters
showAsActionboolean
getTitle(): string
Returns the title of the menu item.
getIcon(): function
Returns the icon for the menu item.
getAction(): function | string
Returns the defined action for the menu item, if any
getParams(): object
Returns the parameters for the menu item.
getIntent(): Intent
Returns the intent for the menu item.
getShowAsAction(): boolean
Returns whether or not the menu item is set to show as an action or not.
orderingMenuItem({title, by}):MenuItem
Convenience method for populating the menu for selecting different fields and directions for ordering a list of documents.
S.documentList()
.title("Products")
.filter("_type == $type")
.params({ type: "product" })
.menuItems([
...S.documentTypeList("product").getMenuItems(),
S.orderingMenuItem({title: 'Title ascending', by: [{field: 'title', direction: 'asc'}]}),
S.orderingMenuItem({title: 'Title descending', by: [{field: 'title', direction: 'desc'}]})
])
orderingMenuItemsForType(typeName):MenuItem[]
Convenience method for returning an array of menu items used to order documents of a given schema type, based on the orderings defined in the schema definition.
REQUIREDschemaTypestring
Schema type name to return orderings for
menuItemsFromInitialValueTemplateItems(items):MenuItem[]
Convenience method for returning an array of menu items used to create new documents based on the given initial value template items.
Note: You should consider using the initialValueTemplates()
method on the pane instead of this method unless you want the menu items to be nested inside the actual menu.
REQUIREDitemsInitialValueTemplateItem[]
Initial value template items. Use
S.initialValueTemplateItem()
to generate these.
S.documentList()
.title('Craft beer & cider')
.filter('_type in $types && isCraft == true')
.params({types: ['beer', 'cider']})
.menuItems(
S.menuItemsFromInitialValueTemplateItems([
S.initialValueTemplateItem('beer', {isCraft: true}),
S.initialValueTemplateItem('cider', {isCraft: true}),
])
)