In this repo, you will find a couple of interesting studio solutions - Each branch has its own focus. If you want to see the most extensive one (where all other branches come together), please skip to Personalisation.
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 |
Check out structure-showroom branch
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 🔥 |
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. |
References are always bidirectional in Sanity - to make them visible you can use a custom component to surface them inside of a document form. This component will also allow editors to open the document referencing the currently open document to the right (just like a normal reference field would).
![]() |
---|
Indicator component for incoming references. |
numberedHeadingsBody.tsx is a schema for Portable Text that enables numbered headings within rich text content, making it easier to structure documents with automatic heading numbers. Those play very nicely with my new Table of Contents plugin (see screenshot below).
NumberedHeadingPTEInput is a custom Portable Text input component, which uses CSS counters to add numbers to each of the headings in the Portable Text field. This component enhances the user experience by providing a clear visual hierarchy of headings, making it easier to navigate and understand the document structure.
![]() |
---|
Numbered headings in the PTE also visually represented inthe Table of contents plugin. |