Compute and AI

Functions quick start

Start building with Functions by initializing and deploying a new function to Sanity's infrastructure.

Functions allow you to run small, single-purpose code whenever your content in Sanity changes. This guide explains how to set up your project, initialize your first blueprint, add a function, and deploy it to Sanity's infrastructure.

Avoid recursive loops

Prerequisites:

  • sanity CLI v3.99.0 or higher 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).

Set up your project

To create your first function, you need to initialize a blueprint. Blueprints are templates that describe Sanity resources. In this case, a blueprint describes how your function and how it 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. It will prompt you for the following:

  • Format: This guide uses TypeScript. For details on the other configuration types, check the Blueprint reference.
  • Project: Select your organization and project. This is the project that will trigger functions.

This creates a few configuration files in your project directory. If you selected TypeScript or JavaScript, it prompts you to install the dependencies. Follow the prompt and run the install command for your package manager of choice.

Create a function

Use the sanity blueprints add function command to add a new function. The CLI prompts you for the following:

  • Function name: Set a name for your function. This determines the function name and the name of its directory. For this example, we'll call it "log-event".
  • Function type: Select the document action that will trigger the function. For this example, select Document Publish.
  • Function language: Select your preferred language. For this example, we'll select TypeScript.

After defining the name and selecting a type, follow the prompt and add the function declaration to your sanity.blueprint.ts configuration. Your file should look like this:

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/
│  ├─ log-event/
│  │  ├─ index.ts

After updating the sanity.blueprint.ts file, open functions/log-event/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

As configured, this function will run every time any document publishes and return the entire document to event.data. This includes system documents. You'll almost always want to scope your functions to specific scenarios and document types with GROQ filters.

Open the sanity.blueprint.ts file and update it to include an event object with the on and filter properties:

The on property takes an array of trigger events. Currently, "publish" is the only valid event type.

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 *[_type == 'post'], only include _type == 'post'.

You can also include a projection property on event to shape the contents passed to the event. Like the filter, only include the contents of the projection. Omit the curly brackets({}).

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

Limited GROQ support

Test the function locally

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

To test a function without passing in any data, run the following:

If you run this on the starter function from earlier, you'll see a response similar to the following:

To test with real data from your project, you can pass a document _id (--document-id) and dataset (--dataset) to fetch a document and pass it to the function's event.

pnpx sanity@latest functions test log-event --document-id 52df8926-1afe-413b-bd23-e9efbc32cea3 --dataset production

You can also pass in JSON as a file (--file) or data string (--data) to substitute the event payload. The file, or data string, should be in JSON format and match the expected input from the event. For example, the shape of your document. Make sure your sample data matches the expectations of your filter and projection.

Update your function to log the event and you'll see the supplied document, data, or file contents in the Logs part of the output the next time you run the test command.

Here is an example command and result from the updated function:

Development playground

Deploy a function

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

You can begin using your function when the deployment is finished. 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 log-event 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 log-event 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 the following:

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?