The Vision Plugin
Allow draft model to be switched off, local context for functions, multiple datasets in Vision and portable text improvements
v3.96.0
✨ Highlights
Allow draft model to be switched off
The draft model can now be switched off by setting the document.drafts.enabled
configuration option to false
. When the draft model is switched off, drafts will not appear in Studio, and users may only create or edit documents inside a release (unless they are live-edit documents).
export default defineConfig({ // ... document: { drafts: { enabled: false } } })
If the draft model is switched off while the dataset contains drafts, a banner will be displayed when opening the document in Studio allowing you to compare the draft content, and publish or discard the obsolete draft. This makes it possible to safely switch off the draft model without running a bulk document migration.
The draft model is switched on by default.
Vision datasets config option
Vision now supports datasets config option, allowing users to configure which datasets to display in the tool
defineConfig({ // ..., plugins: [ visionTool({datasets: ['production', 'test']}), ] })

Improvements to Portable Text Editor
The Portable text Editor now allows you to open referenced documents from annotation popups.
List counts are now improved and should work more predictably. For example, the correct list count for numbered list items outdented to the 10th level will now display correctly.
Functions context now indicates local invocation
Functions run locally now receive a context.local
property set to true
in both the sanity functions test
and sanity functions dev
commands. This allows you to run code specific to local invocations. In production, context.local
is undefined
. See the Functions handler reference for more context properties.
Function dependency management now supports flexible app structures
Functions will now find dependencies at the project-level, or the function-level depending on the location of your package.json
manifests. If a function contains a package.json
and dependencies in the individual function folder, it will use them during testing and deployment. If a function lacks local dependencies, it will use the package.json
located alongside the blueprints configuration file (sanity.blueprint.ts
).
You can learn more in the function dependency management guide.
Coming soon: v4 drops Node.js 18 support
On July 15th, the sanity
package is moving from v3 to v4. The only breaking change is that it now requires Node.js 20, where it previously required Node.js 18. Learn more about why we're making this change and what it means for your apps.
🐛 Notable bugfixes
- Fixes issue where delete changes were not being displayed correctly in Review Changes.
- Restores exports removed in 3.95.0 and adds deprecation warnings to exports related to
scheduled-publishing
from the sanity package. - Fixes an issue where it was possible to create a new document version when the Content Releases feature was turned off for a studio.
Install or upgrade Sanity Studio
To initiate a new Sanity Studio project or upgrade an existing one, please refer to our comprehensive guide on Installing and Upgrading Sanity Studio.
If you are updating from a version earlier than 3.37.0, you should also check out this article to ensure your dependencies are up to date.
Sanity Studio Update: Save Vision Query Results, Custom Components with Intent Handling, and bugfixes
v3.42.0
Install or upgrade Sanity Studio
To initiate a new Sanity Studio project or upgrade an existing one, please refer to our comprehensive guide on Installing and Upgrading Sanity Studio.
If you are updating from a version earlier than 3.37.0, you should also check out this article to ensure your dependencies are up to date.
✨ Highlights
Save Vision Query Results
You can now conveniently save the results of your Sanity Vision queries as JSON or CSV files. Simply run your query and click on the new "save result as" buttons in the bottom right corner.

Custom Components with Intent Handling in Structure Builder
Custom components included in the Structure Builder (like S.component(MyCustomComponent)
) can now handle intents. This is especially useful for routing to custom components from global search results or other links. You can achieve this by using the canHandleIntent
parameter.
S.listItem() .id('translate') .title('Translate Test') .child(S.component(TranslateExample).id('example') .canHandleIntent((intent, params, context) => { console.log(intent, params, context) return true } ))
🐛 Notable Bugfixes
- Fixes an issue where Boolean inputs were not always clearly indicated as read-only and disabled.
- Makes the search/filter in the document "Inspect" dialog case-insensitive.
- Prevents inputs within the Portable Text Editor from calling
element.onFocus()
on any opened block or inline-object, thus avoiding unintended modal closures. - Prevents extra work on preview prepare functions, ensuring better performance.
- Fixes miscellaneous bugs and performance issues with Portable Text Editor's block extras and highlight rendering. For example, pointer events are now correctly disabled to avoid unnecessary cursor changes or rendering thrashes.
- Fixes an issue where the document history panel would appear to load indefinitely
New Help & Resources menu, Vision update
v3.14.0
Installation and upgrading
To initiate a new Studio without installing the CLI globally:
npm create sanity@latest
To upgrade a v3 Studio, run this command in its folder:
npm install sanity@latest
✨ Highlights
Support for Perspectives in Vision

Coinciding with today's studio release, we're bringing support for trying out Perspectives in the vision plugin.
With Perspectives, you can add a single parameter to fetch a either the latest draft (previewDrafts
) or latest published (published
) version of a document.
To learn more about Perspectives, read our announcement post or our documentation.
New Help & Resources menu
We've consolidated some helpful resources to customize the Studio experience, learn more about our latest updates, and connect with our team. You can also compare your current Studio version to the latest version available.

New GROQ functions and versioning
v2021-03-25
This release targeting v2021-03-25
and v2021-10-21
of the Content Lake brings several new function namespaces to GROQ, as well as introduces the first formalized version of the GROQ language specification.
New GROQ functions
There are three new namespaces for functions added to the specification, which have been implemented across all GROQ tooling. These are:
array::
functions: Perform array operations on lists, such as removing all null values, building text strings from a list of names, or generating a list of all unique document _types.
array::compact(<array>)
- removes allnull
values from an arrayarray::join(<array>, <token>)
- concatenates all array elements into one string, separated by a specified token.array::unique(<array>)
- removes duplicate values from an array (this works for values that can be compared for equality, specifically numbers, strings, booleans, andnull
, and will not work for values that are arrays or objects)
math::
functions: Run common mathematical operators on numeric values. For example, you can add the prices across multiple products or return the maximum discount available within a cart of products.
math::avg(<array-of-numbers>)
- calculates the average value (arithmetic mean) of an array of numbers.math::max(<array-of-numbers>)
- returns the largest numeric value of an array of numbers.math::min(<array-of-numbers>)
- returns the smallest numeric value of an array of numbers.math::sum(<array-of-numbers>)
- calculates the sum of an array of numbers.
string::
functions: Manipulate text or validate that information matches a given prefix. For example, get a list of the articles that start with “How to” or split a comma-separated string of author names into an array.
string::split(<string>, <delimiter-token>)
- turns a string into an array of substrings based on a delimiting token.string::startsWith(<string>, <string-pattern>)
- checks if a prefix string exactly matches the start of another string.
To learn all about the new GROQ functions, read the developer update accompanying this release, and visit our documentation.
GROQ1.revision1
With this release, we are also pleased to announce the formal language specification of GROQ, as well as a new versioning scheme. Taking inspiration from other well-known language specs, like HTML and SQL, we settled on the following format:
GROQ-<major version #>.revision<#>
The current version of the specification is GROQ-1.revision1
. This version does not include any breaking changes. To learn more about the history and future of the GROQ language, read the blog post from Co-founder and CTO Simen Svale Skogsrud: Content is Queryable: (Re)Introducing GROQ.