Editorial Workflows & Editor UX7 min read

How to Wire Content Releases Into Your Editorial Workflow

A marketing lead schedules a homepage refresh, a pricing change, and three localized landing pages to go live the morning of a launch.

Published June 28, 2026

A marketing lead schedules a homepage refresh, a pricing change, and three localized landing pages to go live the morning of a launch. Each edit lives in a different content type, touched by a different editor, and nobody can see the launch as one coherent thing until it ships. Then the embargo slips by an hour, one translation publishes early, and the rollback is a frantic series of manual un-publishes while the marketing lead refreshes production and prays. This is the failure mode that ad-hoc scheduling creates: editorial intent scattered across individual documents, with no atomic unit that represents "the launch" and no safe way to preview or reverse it.

Sanity treats this as a first-class workflow problem rather than a calendar feature. As the Content Operating System for the AI era, it gives editorial teams Content Releases, a way to bundle related changes into a single reviewable, schedulable, and reversible unit that sits inside the Studio your developers already ship. This guide is about wiring that primitive into a real editorial process: how releases map to your branching and approval reality, how to preview a future state of the whole site before it goes live, and where the App SDK, Functions, and Roles & Permissions plug in so that "go live" stops being a leap of faith.

Why document-by-document scheduling breaks at launch scale

Most headless CMSes treat scheduling as a property of a single document: set a publish-at timestamp, walk away, hope. That model holds up fine for a lone blog post. It falls apart the moment a launch is what it actually is in practice, a set of interdependent changes that must land together or not at all. The homepage hero references a campaign landing page that references a new pricing object that references localized copy in five markets. Schedule those independently and you have built a distributed system with no transaction boundary. Any one of them can publish a minute early, reference a document that does not exist yet, and render a broken page to real traffic.

The deeper problem is reviewability. A launch reviewer wants to answer one question: "what does the site look like the instant this goes live?" Per-document scheduling cannot answer it, because the future state only exists as a scatter of timestamps in different documents' metadata. There is no single object to open, diff, approve, or hand to legal. So teams compensate with spreadsheets, a shared calendar, and a designated human who babysits the publish window. That human is the transaction boundary, and humans miss embargoes.

Content Releases reframes the unit of work. Instead of N independent scheduled documents, you author one release that contains all the changes, and the release is the thing you preview, approve, schedule, and publish atomically. The interdependencies travel together because they live in the same bundle, which is exactly the property document-level scheduling can never give you.

What a Content Release actually is in the Studio

A Content Release is a named bundle of document changes that editors stage together and publish as one action. Inside Sanity Studio, a release behaves like a workspace for a specific moment in time: editors add new documents, edits to existing documents, and deletions to the release, and those changes stay isolated from the live dataset until the release is published. Nothing in the release affects production until the whole bundle goes live, which is what makes the unit atomic rather than a loose collection of timers.

Because releases live in the Studio, they inherit everything your team already customized there. The Structure Builder navigation, custom input components, validation rules, and Studio Workspaces all apply to documents inside a release the same way they apply to live content. An editor working on a release is not using a separate bolt-on scheduling tool with a thinner UI; they are using the same editor, with the same field-level validation catching the same mistakes, just pointed at a future state of the content rather than the present one.

This is the practical difference between a content system that bolts scheduling on and one where scheduling is part of the content model. A release can be scheduled for a specific publish time, published immediately on approval, or held open indefinitely while the launch firms up. It can also be unscheduled or archived without touching live content, so a slipped launch date is a one-field change rather than a cascade of manual edits. The bundle is the safety property, and the bundle is native.

Previewing the future state of the whole site, not one document

The question reviewers actually need answered is what the live site will look like after a release publishes, with every change in the bundle applied at once. Single-document preview cannot show this, because a preview of one scheduled document still renders against the current state of everything it references. You see the new hero against the old pricing, which is a view of a moment that will never exist in production.

Sanity solves this by letting you query content as of a release. GROQ can resolve references and projections against the dataset with the release's changes layered in, so a frontend can render the entire site as it will appear once the bundle goes live. Wire that into the Presentation Tool and Visual Editing, and a reviewer gets a clickable preview of the future site: navigate the campaign page, follow the link to the new pricing, switch locales, and see every interdependent change rendered together because they are being resolved together. The Live Content API keeps that preview current as editors keep working inside the release, so the review surface is never stale.

This matters most for the failure mode in the introduction. The reason early-publishing translations and dangling references slip through is that nobody could see the assembled launch before it shipped. Release-scoped preview turns the abstract "are we ready?" into a concrete page a stakeholder can click through and sign off on. The reviewer is no longer approving a list of document IDs and timestamps. They are approving a rendered site they can actually read, which is the only review that catches the broken reference before customers do.

Mapping releases to approval gates and roles

A release is only as safe as the governance around who can create, edit, schedule, and publish it. The common mistake is to treat the publish button as the control point. By then the decision has effectively been made; the meaningful gates are upstream, when the release moves from drafting to ready-for-review to approved-to-ship. Each of those transitions is a place where the wrong permission grant turns a safety net into theater.

Sanity's Roles & Permissions let you separate these duties so that the editors assembling a release are not necessarily the people authorized to schedule it for production. You can grant contributors the ability to stage changes into a release while reserving the scheduling and publishing actions for a smaller group, which mirrors how launch sign-off works in most organizations: many hands build the launch, a few hands ship it. Audit logs record who did what and when across that lifecycle, so an embargo question after the fact has an answer that is not someone's memory of a Slack thread.

For teams that need approval logic richer than role checks, Functions can run on content events to enforce gates programmatically: block a release from being marked ready if required locales are missing, notify a reviewer channel when a release is scheduled, or require a legal-approval field to be set before the publish action is allowed. The point is that the editorial workflow, not just the calendar, becomes the system of record for a launch. Approval stops being a verbal agreement and becomes a state the platform tracks, gates on, and logs.

Automating the boring parts with the App SDK and Functions

Once releases are your unit of work, a lot of launch toil becomes automatable, because there is finally a single object to hang automation off. The repetitive work around a launch is rarely the creative part. It is checking that every market has a translation, that every referenced asset exists, that the right people were notified, and that nothing was scheduled into a holiday freeze window. Each of those is a rule, and rules are exactly what you want a machine enforcing rather than a tired human at 6am.

Functions give you serverless handlers that fire on content events, so a release can trigger workflows without anyone clicking anything: when a document is added to a release, kick off machine translation drafts for the missing locales; when a release is scheduled, post the launch summary to the reviewer channel; when it publishes, purge the relevant CDN paths and ping the on-call channel. Because Functions run against the Content Lake, they see the same structured content the editors see, including which documents belong to which release.

The App SDK extends this into the Studio itself. You can build a launch-readiness app that lives next to the content, reads the current release, and renders a checklist: locales present, references resolved, approvals recorded, schedule set. Instead of context-switching to a spreadsheet, the reviewer gets the readiness state where the work already lives. This is the difference between scaling a launch process by adding coordinators and scaling it by encoding the coordination once. The release is the anchor; automation hangs off it.

A rollout pattern: from spreadsheet calendar to governed releases

Migrating to release-based editorial workflow is itself a workflow, and rushing it is how teams end up with releases that nobody trusts. Start by picking one recurring, multi-document launch type, a weekly campaign drop, a monthly pricing update, a coordinated localization push, and model just that as a release. Resist the urge to convert everything at once. You want one team to build muscle memory around staging changes into a bundle, previewing the assembled future state, and shipping atomically before you generalize the pattern.

Next, encode the gates that team already follows informally. Map the spreadsheet columns to real state: who drafts, who reviews, who schedules, who publishes. Translate those into Roles & Permissions so the people boundaries are enforced by the platform rather than honored by convention. Add a single Function that blocks the one mistake that actually hurts you, usually a missing locale or an unresolved reference, before you add a dozen clever ones. A small number of trusted gates beats a wall of brittle automation that editors learn to route around.

Finally, make the preview the ritual. The cultural shift that makes releases stick is that no launch ships without someone clicking through the release-scoped preview in the Presentation Tool first. Once a reviewer has caught a broken cross-reference in preview that would have hit production, the team stops treating the future-state preview as optional. From there, expanding releases to more launch types is incremental, because the hard part, trusting that the bundle is the truth and the preview is real, is already done.

Scheduling and atomic launches across headless platforms

FeatureSanityContentfulStoryblokStrapi
Atomic multi-document launchContent Releases bundle adds, edits, and deletes across documents and publish them as one reversible action.Scheduled actions can group entries into a release, published together at a set time via the scheduling API.Releases group related stories and publish them together on a schedule from the editor.Scheduling is per-entry via Draft & Publish plus a publish-at field or community plugins; no native cross-document bundle.
Preview of the assembled future stateQuery content as of a release with GROQ, then render the whole site future-state in the Presentation Tool with Visual Editing.Preview API plus a preview environment renders scheduled content; assembling a full multi-entry future view is app-built.Visual Editor previews a story; previewing the combined future state of a release is configured per project.Preview is implemented in your frontend; future-state assembly across entries is custom application work.
Approval gates tied to the launch unitRoles & Permissions separate staging from scheduling and publishing; Functions enforce gates on release events.Roles plus Tasks and Workflows (higher tiers) provide approval steps; gate logic on a release is configured.Approval workflows and roles available on higher plans; gating tied to a release is plan-dependent.Role-based access via RBAC; review/approval workflow is largely custom or plugin-based.
Editor parity inside the scheduled unitDocuments in a release use the same customized Studio: Structure Builder, custom inputs, and field validation all apply.Entries in a release use the standard web editor with the same field validation.Stories in a release use the standard Visual Editor and field schema.Entries use the admin panel editor; customization is via the plugin and customization API.
Event-driven launch automationFunctions run serverless on content and release events against the Content Lake; App SDK adds in-Studio readiness apps.Webhooks and scheduled-action APIs trigger external automation; logic runs in your own services.Webhooks and the Management API trigger external pipelines you host.Lifecycle hooks and webhooks trigger custom server-side logic you build and run.
Audit trail across the launch lifecycleAudit logs record create, schedule, and publish actions across the release lifecycle for after-the-fact answers.Audit logs available on higher tiers capture entry and publish events.Activity history records changes; depth and retention vary by plan.Audit logging is self-hosted concern; available via enterprise edition or custom logging.

Ready to try Sanity?

See how Sanity can transform your enterprise content operations.