Functions

Create a Media Library Asset Function

Start building a function that reacts to changes to a Media Library asset.

Media Library Asset Functions allow you to run small, single-purpose code whenever a Media Library sanity.asset document changes. These are the container documents that hold basic metadata, versions, and aspect data.

You can try things like:

  • Compare changes in an asset's aspect data.
  • Kick off a review flow when new versions are added to an asset.
  • Update references when assets are deleted.

This guide explains how to set up your project, initialize your first blueprint, add a function, and deploy it to Sanity's infrastructure.

Experimental feature

Prerequisites:

  • The latest version of sanity CLI (sanity@latest) is recommended to interact with Blueprints and Functions as shown in this guide. You can always run the latest CLI commands with npx sanity@latest.
  • Node.js v22.x. We highly suggest working on this version as it is the same version that your functions will run when deployed to Sanity.
  • An existing project and a role with Deploy Studio permissions (the deployStudio grant).

Avoid recursive loops

Set up your project

To create a function, you need to initialize a blueprint. Blueprints are templates that describe Sanity resources. In this case, a blueprint describes how your function will respond to updates in your Sanity project. We recommend keeping functions and blueprints a level above your Studio directory.

For example, if you have a Marketing Website that uses Sanity, you may have a structure like this:

marketing-site/
├─ studio/
├─ next-app/

If you initialize the blueprint in the marketing-site directory, functions and future resources will live alongside the studio and next-app directory.

Functions and Blueprints match your workflow

Create a blueprint

Initialize your first blueprint with the init command. Replace <project-id> with your project ID, found in manage or your sanity.config.ts file.

This configures a new blueprint for your project, adds a blueprint.config.ts config file to the current directory (.), and creates a new stack named production.

Follow the prompt and run your package manager’s install command to add the dependencies.

Create a function

Use the sanity blueprints add function command to add a new function. You can also run it without any flags for interactive mode.

After running the command, follow the prompt and add the function declaration to your sanity.blueprint.ts configuration. Your file should look like this:

Replace my-media-library-id with your Media Library ID.

The on property is already set and takes an array of trigger events:

  • create: Fires when a new document is created for the first time.
  • update: Fires when changes are made to an existing document.
  • delete: Fires when an asset document is deleted.

For existing, published documents, update will only trigger when a draft is published and updates the document. In many cases where you'd use update on published documents, it may be better to use ['create', 'update'] to ensure new documents also trigger the function. Learn more about document lifecycles.

This is the minimal configuration for defining a Media Library Asset Function in a blueprint file. You can see all available options in the Function section of the Blueprints configuration reference documentation.

If you've followed the directory structure mentioned earlier, you'll see it grow to something like this:

marketing-site/
├─ studio/
├─ next-app/
├─ sanity.blueprint.ts
├─ package.json
├─ node_modules/
├─ functions/
│  ├─ asset-update/
│  │  ├─ index.ts

After updating the sanity.blueprint.ts file, open functions/asset-update/index.ts in your editor.

The documentEventHandler function

Every function exports a handler from the index file.

The handler receives a context and an event. The context contains information to help you interact with your Sanity datastore, such as clientOptions to configure a @sanity/client.

The event contains information about the action that triggered the function. Most functions will use event.data, which contains the contents of the Sanity document. You can learn more in the Function handler reference.

Limit the scope with GROQ

This function will run every time any Media Library asset documents (documents with a _type of sanity.asset) change and it will return the entire document to event.data. Let’s narrow the scope by writing a GROQ filter.

Filters

Open the sanity.blueprint.ts file and add a filter to the event object:

This filter causes the function to only run when private assets are created or updated.

filter accepts a GROQ filter that limits which documents will trigger the function. Only include the filter contents, the portion inside the square brackets, of your GROQ query. For example, rather than *[cdnAccessPolicy == 'private'], only include cdnAccessPolicy == 'post'.

Projections

Projections let you shape the contents passed to the event. Set the projection property on event. If you want your function to receive an object instead of individual attributes, ensure your projection is wrapped in curly braces ({}) as shown in the example.

Projections don't limit what fields trigger the function, only which data is passed into the function.

GROQ is a powerful query language, and with features such as delta functions —to help you determine what in a document changed as well as how it changed—you can narrow the scope even farther. Check out the GROQ Query Cheat Sheet for more ideas, and the Functions cheat sheet for additional function-specific techniques.

Test the function locally

You can test functions locally with the functions development playground. Local testing is a great way to experiment without affecting your usage quota.

To launch the development playground, run the following:

If you run this on the starter function from earlier, you'll see the default output message in the console pane.

A screenshot of the functions playground interface

To test with real data from your Media Library, you can pass a document _id and select your library ID to fetch an asset document and pass it to the function's event. Don't forget to press the download button next to the document ID to populate the input. You can also manually enter a document-like shape. In either case, make sure it matches your projection criteria.

Update your function to log the event and you'll see the supplied document details the next time you run the function in the playground.

Development playground

Deploy a function

Once you're satisfied that the function works as expected, deploy it by deploying the blueprint stack.

You can begin using your function when the deployment finishes. If you set a filter earlier, edit a document that matches it and publish the changes to trigger the function.

If you need to change the function, update your code and re-run the deploy command to push the new changes live.

Check the logs

When you tested the function locally, you saw the logs directly in your console. Once deployed, the function and its logs are in the cloud.

View the logs with the functions logs command. Replace asset-update with your function name.

This command outputs the function's logs. Try updating your document, publishing the change, and running the command again to see new logs.

System documents

Destroy a deployed blueprint

Sometimes you want to remove a deployed function so it won't run anymore or affect any future usage quotas. The blueprints destroy command removes, or undeploys, the blueprint and all of its functions from Sanity's infrastructure. It does not remove your local files.

Remove the test function:

To remove the function from the blueprint locally, you can remove it from the resources array in the sanity.blueprint.ts file, then delete the asset-update folder from the functions directory.

Redeploying a destroyed blueprint

When you run blueprints destroy, it's as if you never used blueprints init during setup. The only difference is you still have all the files in your directory. To use this blueprint again and redeploy it, you'll need to let Sanity know about it. You can do this by running init again:

This launches an editing interface that lets you reconfigure the blueprint, if needed, and it reconnects the blueprint to Sanity. Now you can add more functions or redeploy. Keep in mind that any environment variables added before destroying the blueprint will not carry over.

Was this page helpful?