Cloud Authoring: A Branch Workflow Content Teams Can Actually Use

Giving non-engineers the ability to publish directly — without making engineers nervous about it.

Company
Knapsack
Role
Senior Product Designer
Platform
SaaS Web App
Project Date
September 2022
Cloud Authoring: A Branch Workflow Content Teams Can Actually Use

What we were trying to solve

When I joined Knapsack, users entered edit mode, made changes, hit "Propose Changes," and opened a PR. Then they waited for an engineer to merge it before anything went live. For content updates that didn't touch code, non-engineers were blocked on engineering availability — days of waiting for changes that should have shipped in minutes.

Designers and content authors could write the change. They just couldn't ship it.

The before state. A single edit mode with a "Propose Changes" button that opened a PR, then handed off to engineering to merge.

The ask: give authorized users the ability to publish directly through the app, merging the PR without engineering involvement, while keeping the underlying Git workflow intact. That meant solving two connected problems: replacing the old flat edit mode with a branch-based model, and building a permission model that gave non-engineers publishing power without making engineers nervous about who could merge to main.

Where I fit in

As Senior Product Designer, I owned end-to-end product definition, UX, and cross-functional alignment — defining the branch-based mental model, designing the full authoring and publishing workflow, and navigating the tension between teams who wanted frictionless publishing and stakeholders who needed confidence that the wrong people couldn't ship to production unreviewed.

A key early alignment with engineering: the app would always create a PR in the Git provider, even for direct publishes, and then merge it programmatically. That kept Git history intact and gave engineering teams an audit trail they could trust — essential for getting buy-in.

I also owned the edge cases: merge conflicts, failed merges, uneditable branch states, and the migration path for customers whose content still lived in the database. Each needed explicit UX and copy before we finalized the design.

How I approached it

The old experience had no concept of a branch — users just entered edit mode and proposed when ready. Introducing branching meant asking everyone to adopt a new mental model: a branch is a draft, and publishing or requesting review is how it ships. That framing had to work for content authors while mapping to concepts engineers already trusted. I tested it with both groups early.

The permission model was a separate track. The core tension wasn't technical — it was organizational. Engineers and admins were genuinely nervous about giving non-engineers the ability to merge to main. The solution: scope publish permissions to workspace admins only, and reframe "Propose Changes" as "Request Review" for everyone else. Teams with formal review cultures kept their PR-and-wait process; teams with trusted authors could publish directly without a bottleneck.

Before publishing or requesting review, all users saw a summary of everything changed on the branch: pages edited, tokens updated, other modified content. For admins, this was the last checkpoint before merging. For everyone else, it was what they were handing off for review. One shared step, same mental model across roles.

Edge cases were first-class throughout: what does an author see on a branch submitted for review and no longer editable? What happens during a merge conflict or failed merge? Each got explicit UX and copy before we finalized the design.

The calls that mattered

Branch model vs. per-page draft/publish

The simpler option was a CMS-style per-page draft/publish. We didn't go that way because users weren't editing one page at a time — they were updating multiple pages, tokens, navigation, and interconnected content together. A per-page model would have fragmented that work, created inconsistent published states, and made it genuinely difficult to review or roll back a coherent set of changes. Branching solved it naturally: everything in a session lives on one branch, gets reviewed together, and ships as a unit.

Request Review vs. Publish as separate actions

Keeping these as two distinct actions — rather than collapsing them or hiding one behind a permission check — was right even though it added surface area to the UI. The distinction is meaningful: teams with formal review cultures need a PR and an engineer in the loop; teams with publish-authorized admins want to merge immediately. Reframing "Propose Changes" as "Request Review" also made the action clearer. You're explicitly handing something off for someone to act on.

A shared interstitial for both roles

It would have been easy to skip the change summary for admins on the assumption they already know what they changed. But the summary served a real purpose: it was a forcing function to review scope before shipping, and it made "Publish" feel considered rather than accidental. The only thing that differed between the two flows was the available action at the end.

Scoping publish to admins

Opening publish access to all users would have been simpler, but it would have undermined adoption with customers whose engineers were already skeptical about non-engineers touching Git at all. Giving admins control over who could publish was what made the feature trustworthy enough to roll out broadly. The "Review Requested" queue also gave those teams a clear, contained place to manage the handoff without leaving the app.

What actually shipped

Cloud authoring replaced the old flat edit mode with a full draft-to-published lifecycle. Anecdotally, the impact was immediate for customers who had been waiting days for engineers to merge documentation updates. Design system content that used to sit in PR limbo could be published by the people who owned it.

Branch creation

Authors create a named branch from latest directly in the app. Knapsack creates it in the customer's Git provider via provider APIs and stays in sync via webhooks.

Users create a new branch to enter an editable state.

Publish and Request Review

Admins can publish directly from the interstitial, merging the branch to main without engineering involvement. Non-admins request review, which routes the branch into a "Review Requested" queue for admins to act on inside the app. Before publishing or requesting review, all users see a summary of what's changed on the branch so nothing ships without a deliberate review of scope.

Non admins are able to request review of their changes to to contribute.
After reviewing the changes an admin can publish the branch, merging it to main

Branch status lifecycle

An explicit status reflecting where a branch stands at any moment (in progress, review requested, or published) with clear guidance when a branch is no longer editable.

Branches list communicating status
Branches list communicating status
Branch status in the app bar
Branch status in the app bar
Branch status in branch details menu
Branch status in branch details menu

What I'd do differently

The migration path for customers with content still in the database was handled, but later than it should have been. It was a known constraint from the start. Any project with an existing-state problem benefits from pulling that forward.

The permission model work reinforced something I now carry into every project involving access or roles: the hard part is almost never the UI. Engineers weren't wrong to be cautious about who could merge to main. The design work that actually mattered was finding a model that addressed that concern directly, not smoothing over it with a simplified interface that would have eroded trust the first time something unexpected shipped.

This project also deepened my conviction that introducing a new mental model is itself a design problem. "Branch = draft, merge = publish" wasn't obvious to non-engineers. It needed to be introduced carefully, tested early, and reflected consistently in every piece of copy and UI. Getting that right before touching the interface made every downstream decision faster.

Next Selected WorkVivid Seats App 3.0: An App Worth Coming Back To   ↗