In this branch you will find a couple structures for the Sanity Studio that highlight how to use the Studio to its full potential.
Have a look:
This is the most basic structure that you can use to get started with the Studio. It shows how to create a simple structure which nests documents and its incoming references.
![]() |
---|
X-by-Y structure example using a parent-child taxonomy |
If you are using the document level i18n plugin and control languages with document, I found a way to create templates for this use case! There is also a way to configure your sites navigation and nesting without a parent-child relationship, which is a common use case for pages and create a structure to display that in the Studio.
![]() |
---|
This example comes with i18n templates, which are based on language documents and more! |
And for the main attraction of this showroom, I created a recursive parent-child structure with infinite nesting, and the ability to create new child draft documents inside of each structure! It even comes with intent handling for 🤯.
Although this works differently than the default template driven workflow, it is a neat solution for a special occasion. This is especially useful for taxonomies, categories, and other hierarchical structures.
I am very proud of this 🦚
!!Be aware that this structure is not the most performant one, so use it with care and only for simple document types!!
![]() |
---|
infinite nesting WITH the ability to create new child draft documents 🔥 |
Check out main branch
Main is the most minimal one and contains only the basic setup.
Check out dynamic-lists branch
This branch shows how to create a dynamic list of options that does not require developer intervention to edit.
![]() |
---|
Dynamic list options based on listOption documents, which have fields for description and more... |
Check out dynamic-languages branch
In this step, I add some complexity and implement the same mechanism of document-based configs to handle languages in the Studio -> even plugins and structures are dynamically configured based on the languages you have in your dataset.
As you can see below, all language documents will be available to the document- and field-level i18n plugins.
![]() |
---|
Language documents are used to control internationalisation from the Studio |
Check out dynamic-markets branch
uses the setup of the dynamic languages and adds a new layer of complexity by adding markets to the mix. those markets reference languages, and the Studio uses those markets and languages to dynamically create workspaces, with the market's languages also playing into plugins and structures.
![]() |
---|
Markets get used to generate dynamic workspaces on runtime |
![]() |
---|
A markets languages are then also used to generate dynamic structures for each market workspace |
Check out personalisation branch
When it comes to personalising the Studio, I added a bit more complexity to the mix. This means that the Studio will now automagically create person
documents for each Studio member and allow members to add bookmarks and languages to their person
. This document can be extended to meet all other needs as well and can be fed into permission with content permissions because we can now use the language settings for every member to remove write access from specific translated documents without the need to do this in the manage console.
Check out recycling-bin branch
Here we take a step back from all the personalisation and dynamic stuff and focus on a more basic setup, but one that is very useful. This branch shows how to create a recycling bin for your deleted published documents. You can find more about this solution in the branches readme or this guide: https://www.sanity.io/guides/bin-for-restoring-deleted-documents
![]() |
---|
With this solution any published document that is deleted can be restored by editors. |
Check out rebasing-releases-and-drafts branch
When drafts and release versions exist and are edited at the same time, they can diverge from each other in unexpected ways. When the release is then published, the existing draft can become out of sync. Those out of sync drafts can then override existing release-based and already published changes -> lastPublishedAt
values could help with simple comparisons.
![]() |
---|
Drafts and releases can get out of sync - and there is a simple soluiton to make sure unintentional changes are published |
This branch shows how to use the `lastPublishedAt` value to rebase the draft with the latest published document. This is a very useful solution for teams that work with drafts and releases at the same time.
The solution uses a function, blueprints and an extended publish
document action to achieve this.
Make sure to read the documentation before, so you know what functions and blueprints do - and how to deploy those in your own projects.
![]() |
---|
Example from the studio - and preview of the solution in action |
#### Specials
It's worth hovering over some of the parts of the custom components because there are a lot of user-shortcuts and hidden features.
On top of all those goodies, I also added a bookmark inspector, which can be opened in all documents (button in the document header) and shows all bookmarks the current user has.
Document inspectors can be used for a huge range of solutions like inline documentation, a table of contents, todos, helpers, and many more.
![]() |
---|
Document inspectors are an amazing way to display data wherever the editor is working. |
A handy dashboard helps to add more personalisation, but the same is also possible in the structure now.
A custom tool, like this dashboard, is one of the most useful but underused components. Instead of building super complex lists for the structure, you can help your editors work more efficiently by allowing them to see things in one visual representation. Since you can build this from scratch you can also add bulk editing and other things into the mix, allow complex multi-document data to be visible in a table, and so much more
![]() |
---|
Structured content can be hard to always understand - help your editors by condensing information which is split across documents into a simple react interface. |