Tutorials

Content Approval Workflow: Roles, Versions and Release

A practical content approval workflow template with a state table, version example, data model, roles, and acceptance checks.

Start building for free
4 min readPublished
Author editor and publisher reviewing separate document versions
On this page

A reliable content approval workflow assigns each draft a version, a named reviewer, and a publish handoff. Approval belongs to the exact version reviewed: if an author changes the copy, create a new version and send it through review again. A green approval status must never publish content by itself.

Download the form field specification

Use explicit states and owners

State Owner and action Next state
draft Author edits a working copy and submits a version. in_review
in_review Editor reviews the locked version and records approve or request changes. approved or changes_requested
changes_requested Author creates a new version and responds to feedback. in_review
approved The approved version waits for the publisher. handed_off or archived
handed_off Publisher sends that version to the CMS or publishing queue. published or handoff_failed
published A receipt records where and when the version went live. archived or a new draft version

A sample editorial item could be “Spring registration update.” Version 1 changes the dates and is approved by editor Jordan Lee on October 6. The author then fixes a broken link. Save that edit as version 2 with a new timestamp and content hash; version 1’s approval stays attached to version 1, so version 2 returns to in_review. After the editor approves version 2, the publisher can hand it off and record the CMS URL and receipt. The sequence makes clear who approved what and whether the page was actually published.

Store the version and decision separately

Author editor and publisher reviewing separate document versions

AI-generated editorial concept; not a screenshot of a deployed app.

This suggested schema is an application design, not an Atoms feature specification:

Table Example fields Purpose
content_items id, title, content_type, owner_id, current_version_id, status One stable identity for the content item.
versions id, content_item_id, version_number, body_snapshot, metadata_snapshot, content_hash, created_by, created_at Immutable copy of the text and publishing fields reviewed.
review_steps id, version_id, reviewer_id, decision, comment, decided_at One reviewer’s decision on one exact version.
approvals id, version_id, approved_by, approved_at, approval_scope, content_hash Explicit record that a given version passed review.
publish_receipts id, version_id, destination, external_id, published_at, result Evidence of a separate publishing handoff.

Give authors permission to create versions and submit their own items. Editors can approve or request changes, but cannot overwrite an approved version. Publishers can hand off only a version whose approval record matches its current content hash. Assigned team readers can see status and approved previews; public visitors see only published content. Restrict internal feedback and drafts to assigned team members. With Supabase, enable row-level security on each exposed table and define grants plus operation-specific policies; the row policy alone does not replace table grants. Supabase Row Level Security guide

When copy changes, do not edit the snapshot that was approved. Create a new versions row, update current_version_id, clear the item’s current approval state, and create a review step. If the system cannot verify that the current hash matches the approved hash, block handoff and return the item to review. This rule covers small edits such as a corrected URL as well as larger rewrites.

Keep approval separate from publication

Approval means the reviewer accepted a version; it does not mean a CMS received it or published it. Make the publisher’s next action explicit: copy the approved content to a publishing queue, call a verified CMS action, or hand off a link to the responsible person. Store the result, destination, external ID, and time in publish_receipts. If the connection fails, show handoff_failed; do not mark the item published until the destination confirms it.

Atoms’ integration guide says each connector has its own actions and permissions, and the available actions can vary by account and release. Check the current connector catalog and review any external-write confirmation before relying on a CMS handoff. Verify the result in the destination after a write. Atoms integration guide

For persistence, choose Atoms Cloud or connect one Supabase project to the Atoms project. The Supabase guide says connecting the database does not add the content workflow automatically; build the feature, then test save, refresh, edit, and readback in both the app and the selected table. Atoms’ Supabase guide

Acceptance checks for the workflow

Seed one author, two editors, one publisher, and two content items. Verify that the author can submit an item, an assigned editor can approve version 1, and the publisher sees it in the handoff queue. Edit the copy after approval and confirm the app creates version 2, marks it in_review, and removes it from the eligible handoff list. Approve version 2, hand it off, and confirm the receipt points to version 2. Then sign in as an unrelated author and verify that private drafts and reviewer notes are unavailable.

Also test a rejected handoff, a retry, an approval by an unauthorized role, and an attempt to publish a version whose content hash has changed. Refresh after each transition and confirm the same state and decision remain. The team can use Atoms’ spreadsheet-to-web-app guide as a starting point for turning an existing tracker into an app.

Atoms build prompt

text
Build a content approval workflow using Supabase.
Use tables content_items, versions, review_steps, approvals, publish_receipts.
Choose Supabase as the only backend for this project.
Create roles author, editor, publisher, and reader.
Authors can create items and versions for assigned content.
Editors can review assigned versions and approve or request changes.
Publishers can hand off approved versions and record receipts.
Assigned team readers can view status and approved previews.
Public visitors can read only published content.
Keep drafts, comments, and review decisions private to assigned team members.
Store each version as an immutable body and metadata snapshot.
Store a content hash on every version and approval.
Link every review step and approval to one version ID and hash.
If copy changes, create a new version and reset the item to in_review.
Never carry approval from one version to another.
Block handoff when current content hash differs from approved hash.
Approval must not set publication state.
Allow handoff only to publisher and only after a matching approval exists.
Record destination, external ID, time, and result in publish_receipts.
Mark published only after a successful destination receipt.
Show handoff_failed when the destination rejects or cannot confirm the write.
Seed one author, two editors, one publisher, two items, and three versions.
Test draft submission, request changes, re-review, approval, and handoff.
Edit approved copy and confirm a fresh version and approval are required.
Try unauthorized approval and unauthorized publishing; both must be denied.
Try handoff with a stale hash; it must be blocked.
Refresh after every transition and confirm state and history persist.
Test two accounts and verify drafts and reviewer notes stay private.
Do not claim a CMS connector action unless it appears in the current connector catalog.
If an external write is available, request confirmation and record its receipt.

Copy the build brief and use it to create your version in Atoms.

Build a review workflow
Share this article
Made with Atoms

Your next idea starts here.

Turn what you learned into a working app or website.

Start building for free