How to securely handle secrets for triggering builds from hosted Sanity Studio?
You're right to be cautious about secrets in environment variables! The documentation correctly warns that any environment variables prefixed with SANITY_STUDIO_ are not secret — they get bundled into your frontend code and are visible to anyone who inspects your deployed Studio.
For your use case of triggering a GitLab pipeline when content changes, here's the recommended modern approach:
Use Sanity Functions (Recommended)
Sanity Functions are the best solution for this. They're serverless functions that run on Sanity's infrastructure and can securely store secrets. Here's why they're perfect for your needs:
- Secure secret management: Functions support environment variables that are truly secret and never exposed to the frontend
- Event-driven: They automatically trigger on document changes (publish, create, update, delete)
- No external hosting: Everything runs on Sanity's infrastructure
- Direct integration: No need to expose tokens in your Studio code
You'd set it up like this:
- Initialize a Blueprint with
sanity functions init - Create a function that triggers on document publish events
- Store your GitLab trigger token as a function environment variable (these are secure)
- Make an HTTP request to GitLab's API to trigger your pipeline
The function would look something like:
export default async function(event) {
const gitlabToken = process.env.GITLAB_TRIGGER_TOKEN; // Secure!
// Call GitLab API to trigger pipeline
await fetch('https://gitlab.com/api/v4/projects/YOUR_PROJECT/trigger/pipeline', {
method: 'POST',
headers: { 'PRIVATE-TOKEN': gitlabToken },
body: JSON.stringify({ ref: 'main' })
});
}Alternative: Webhooks
If you already have external infrastructure or prefer webhooks, you can use Sanity's GROQ-powered webhooks. The webhook secret would be stored on Sanity's side (not in your Studio), and you'd set up an endpoint on your server to receive the webhook and trigger GitLab. This keeps secrets out of your frontend, but requires you to host and maintain the webhook receiver.
Why Not Document Actions or Plugins?
Document Actions run in the Studio (browser), so any API tokens would be exposed in the frontend code — the same problem as SANITY_STUDIO_ environment variables. Plugins have the same limitation since they're part of the Studio bundle.
The key principle: anything that runs in the browser cannot securely hold secrets. You need server-side code, which is exactly what Functions provide without requiring your own infrastructure.
Functions are the modern, recommended approach for this type of automation, and they solve your security concern perfectly while being simpler to set up than webhooks + external hosting.
Show original thread4 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.