Blueprint configuration reference
New Function Type: Media Library Asset Functions
v2025-11-06
We've added a new Sanity Function type that lets you respond to changes in your media library. This update brings the same event-driven capabilities from document functions to your media library assets.
✨ Highlights
React to Media Library asset events
You can now run functions whenever assets are uploaded, updated, or deleted in your media library. This new asset function type extends the event-driven architecture already available for documents, giving you more control over your content workflow automation.
Use this new function type to:
- Know when new versions of an asset are created.
- Clean up dependencies when assets are deleted.
- Trigger notifications or webhooks for asset events.
Here's an example of defining a Media Library asset function:
import { defineBlueprint, defineMediaLibraryAssetFunction } from '@sanity/blueprints'
export default defineBlueprint({
resources: [
defineMediaLibraryAssetFunction({
name: 'ml-asset',
event: {
on: ['update'],
filter: "delta::changedAny(title)",
projection: "{_id, title, assetType}",
resource: {
type: 'media-library',
id: 'mlFqEeKZYecz',
}
},
})
],
})This function type specifically targets documents with a _type of sanity.asset. You can apply additional filters, as shown in the example above, but only sanity.asset documents will invoke the function.
More Media Library functions will come in the future to accommodate more document types.
To get started, update to the latest @sanity/blueprints and @sanity/functions libraries using npm or pnpm, and ensure you're using the latest sanity CLI (v4.14.0). ML support in functions requires @sanity/blueprints v0.4.0 or later and @sanity/functions v1.1.0 or later.
For more information about Functions, see the Sanity Functions documentation.
Note: This functionality requires that your plan includes access to Media Library.
Introducing Functions dataset scoping
v2025-09-22
You can now limit which document changes will invoke your Functions by specifying a particular dataset as part of the housing Blueprint. This allows you to target, with greater precision, when your Functions invoke by "scoping" your Function triggers to specific resources.
This new feature is available by specifying the event.resource field of your Function Blueprint definition. Previously, your Function definition would look something like the following (assuming you use the defineDocumentFunction helper from the @sanity/blueprints package):
import {defineBlueprint, defineDocumentFunction} from '@sanity/blueprints'
export default defineBlueprint({
resources: [
defineDocumentFunction({
name: "log-event",
event: {
on: ["update"],
filter: "_type == 'post'",
},
})
]
})This Function will trigger whenever a _type: 'post' document was updated - regardless of which dataset the document was present in. For Projects with multiple datasets, this could lead to confusing outcomes and Function executions.
Now, you can specify documents from which dataset should trigger your Functions:
import {defineBlueprint, defineDocumentFunction} from '@sanity/blueprints'
export default defineBlueprint({
resources: [
defineDocumentFunction({
name: "log-event",
event: {
on: ["update"],
filter: "_type == 'post'",
resource: {
type: 'dataset',
id: 'myProjectId.production'
},
},
})
]
})The above configuration would trigger the log-event Function whenever a document of type 'post' from the production dataset within the project with ID myProjectId gets updated.
You can also explicitly specify "all datasets" my replacing the dataset name with *. Using the same example as above, that would yield myProjectId.*. This is the default behavior, so you can also omit event.resource altogether.
For TypeScript or JavaScript blueprints configurations, update to at least version 0.3.0 of the @sanity/blueprints library.
# In the directory housing your sanity.blueprint.ts/js file npm install @sanity/blueprints@latest
# In the directory housing your sanity.blueprint.ts/js file pnpm add @sanity/blueprints@latest
# In the directory housing your sanity.blueprint.ts/js file yarn add @sanity/blueprints@latest
# In the directory housing your sanity.blueprint.ts/js file bun add @sanity/blueprints@latest
This sets up triggering Functions with different kinds of resource.types. Stay tuned for more in the near future!
Functions new document change events and filtering options!
v2025-08-20
We are excited to give developers more document change events to trigger their Functions! The new events are:
create: Emitted when a document is created.delete: Emitted when a document is deleted.update: Emitted when a document is updated.
Additionally, two new boolean toggles are available when defining the triggering event for your Functions:
includeDrafts: Whether the event should be emitted with respect to draft documents. Defaults tofalse.includeAllVersions: Whether the event should be emitted with respect to version documents (documents part of a Content Release). Defaults tofalse.
Keep in mind that combining update with includeDrafts and/or includeAllVersions may result in many, rapid, invocations whenever changes are synced. See the rate limits and use with caution.
Note that these new events and options have significant overlap with the existing publish event. In fact, publish can be defined as:
on: ['create', 'update'], andincludeAllVersions: true
The publish event was an early beta attempt at encapsulating a useful, initial first-pass at a Functions source event.
These new additions set up a deprecation of the publish event, so keep an eye out for that to officially land sometime in the near future. If you want to get ahead of things, you can update any existing function events that use on: ['publish'] to instead use the on and includeAllVersions values mentioned above—or make them more specific for your needs.
Support for these new events and filters landed in the following tools under the specified versions. Upgrade to at least these versions to take advantage of the changes:
@sanity/blueprintsv0.2.0sanityCLI v4.5.0
Functions `projection` breaking change
v2025-08-06
Why we're making the change
⚠️ Previously, we accepted GROQ projections in function event definitions that were not wrapped in curly braces ({}). Behind the scenes, we would transparently wrap your projection with curly braces.
📣 In order to better support the full GROQ specification, as of now, if you wish to receive an object as a projection in your function invocation, you are required to wrap your projection in curly braces.
Before
❌ Previously, you could provide the following projection that expressed "give me an object with _id and type properties":
{
"on": ["publish"],
"filter": "_type == 'post'",
"projection": "_id, type"
}Now, trying to create or update a function with the above projection will yield an error like:
Failed to manage function subscription: Failed to validate document change event rule: projection is invalid: parse error at position 3: unable to parse entire expression"
After
✅ Instead, wrap the projection with curly braces:
{
"on": ["publish"],
"filter": "_type == 'post'",
"projection": "{_id, type}"
}This explicitly says that you want an object.
Existing functions
If you have an existing function deployed to Sanity, we've migrated the deployed code to the new syntax. Your function will continue to work as it has without any intervention.
Prior to your next deployment, you will need to update any projections to use the new syntax. In short, wrap your projection in curly braces as shown above and then deploy the changes.
Faster dev server, Portable Text plugins, new Blueprints syntax, and more improvements
v3.92.0
✨ Highlights
Faster dev server
Improves cold starts on sanity dev by eliminating optimized dependencies changed. reloading cycles in vite. We now use server.warmup to ensure cold starts are much less cold and jarring. 🫡
Improved timezone UX for datetime fields
Adds the ability to control the display of datetime fields with regard to timezones. Use the new displayTimeZone field option to specify the time zone used for displaying and interacting with the timestamp in Studio. Each user may personalize the time zone they see (this can be prevented by setting the allowTimeZoneSwitch field option to false).

It's now possible to deprecate Portable Text blocks
Custom Portable Text block objects may now be marked as deprecated. When a block is deprecated in the schema, its corresponding toolbar button will be inactive and display a tooltip with the provided deprecated.reason.
defineArrayMember({
name: 'customBlock',
type: 'object',
deprecated: {
reason: 'This block type is deprecated and will be removed in the future.',
},
fields: [
// ...
],
})Custom Portable Text plugins come to Studio
The Portable Text Editor's Behavior API is now compatible with Studio in a format that is familiar to creators of custom components. Create your own plugins, or add an existing one to your block content. Follow our guide for creating a new Portable Text Editor plugin to get started.
Blueprints now supports TS/JS configuration formats
When you initialize a new Blueprint with sanity blueprints init, you're now able to select TypeScript or JavaScript—in addition to JSON—for the configuration format. You can update existing blueprint configurations to this format by adding the @sanity/blueprints package and updating your configuration file.
import { defineBlueprint, defineDocumentFunction } from '@sanity/blueprints'
export default defineBlueprint({
resources: [
defineDocumentFunction({
name: 'Create Fancy Report',
src: 'functions/create-fancy-report',
memory: 2,
timeout: 360,
event: {
on: ['publish'],
filter: "_type == 'customer'",
projection: "totalSpend, lastOrderDate",
}
}),
],
})Other features
- Bumps version of React to 19 for studios created using
sanity initornpm create sanity. - Clicking to edit the visual editing overlay for slugs now focuses the slug input, rather than doing nothing. It's amazing what modern technology can do. 🤯
- When using Studio inside Dashboard, it's now possible to switch Studio workspaces again.
- If the first document action is custom, it will now be displayed as the primary document action when viewing document versions. Previously, it was only available by opening the document actions menu.
🐛 Notable bugfixes
- Fixes an issue that caused the history cleared event to show in between edit events.
- Fixes an issue that caused comments created in version documents to sometimes contain the title of the draft or published version in the notification email.
- Fixes a bug that caused React's maximum render depth to be exceeded if a custom component used lazy loading. In production builds, this was reported as minified React error
#185. This caused the@sanity/color-inputplugin to crash when used inside a Portable Text annotation. - Fixes an issue that caused comments created in arrays of objects to sometimes not be displayed.
- Fixes an issue that caused restoration of deleted documents to restore the first revision, rather than the most recent revision prior to deletion.
- Fixes an issue that caused users of
next@canary, orreact@canary, to see agetAttribute is not a functionerror when attempting to edit a link in a Portable Text input field. You shouldn't have to choose between being able to fully use Sanity Studio's Portable Text Editor, or fun new React versions and features, and you no longer have to! - Fixes incorrect filtering results in timezone modal.
- Fixes an issue where running
sanity initin unattended mode or with--create-projectsometimes created a new organization. - Skips auto-update-prompts during
sanity buildandsanity deployfor non-interactive sessions. - Restores the Continue anyway option to
sanity deployandsanity build. - Sometimes a confusing
Duplicate instances of context "sanity/_singletons/context/media-library"warning was logged to the console. It's confusing because it implies that the user did something wrong. This time it was us, not you. ❤
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.