Skip to content

Editor workflow: per-entry 'Ready to publish' flag + 'Publish all marked' action (beyond branches) #1541

Description

@nurkamol

Use case

We run a marketing site on Keystatic in GitHub mode. Editors make 5–20 small content edits throughout the day (typo fixes, copy tweaks, swapping a tagline, adding a testimonial, etc.). Today, every Save commits straight to main, which:

  • Triggers a fresh production build per Save (Cloudflare Workers Build, in our case — but the same applies to Vercel, Netlify, etc.).
  • Clutters git history with one micro-commit per change ("Update Hero", "Update Hero", "Update Hero", …).
  • Means a typo in any save ships to production immediately.

What's already possible

We know about branchPrefix + branch-based editing — we use it, and PREVIEW.md in our repo documents a workflow where editors pick a long-lived cms/staging branch in the picker, save many times, then merge a PR to publish.

That does solve the deploy-per-save problem, and we recommend it as the answer today. Thank you for that primitive — it's the foundation.

The UX gap

Non-technical editors still need to:

  1. Remember to flip the branch picker to cms/staging before every session (easy to forget; defaults to main).
  2. Leave Keystatic and go to GitHub to open + merge the PR to publish.
  3. Understand what "merge a PR" means.

For technical users this is trivial. For marketing/content editors who have never opened a PR, it's the bottleneck — they often default to editing on main because the picker is right there.

Proposed feature

A first-class "draft → publish" workflow built on top of the existing branch primitive, expressed in admin-friendly language:

  1. A per-entry "Ready to publish" flag in each entry's Save dialog (or as a toggle in the entry form). When unchecked, Save commits to a staging branch. When checked + Save, the entry is marked as ready in the staging branch.
  2. A dashboard surface listing entries currently staged (changed on the staging branch vs. main), with their "Ready to publish" status.
  3. A single "Publish all ready" / "Publish all changes" button that merges the staging branch into the production branch (i.e. opens + auto-merges the PR via the GitHub App).
  4. Optional: a defaultBranch config (e.g. "cms/staging") so the picker doesn't default to main — this alone would already remove a big footgun.

The branch primitive stays exactly as it is; this is purely a UX layer on top, so technical users who prefer raw branches lose nothing.

Why this isn't easily DIY-able

We can — and probably will — build a custom admin page that lists open cms/* branches and exposes a merge button via the GitHub App token. But:

  • Re-implementing the auth Keystatic already does on a sibling route is non-trivial.
  • It's a separate admin surface that editors have to remember exists.
  • It drifts as Keystatic evolves.

A first-class flow inside Keystatic itself would be a much better fit, and would benefit every team running Keystatic at any reasonable editing volume.

Smaller-scope wins, if a full design is out of scope

Either of these alone would already be a big improvement:

  • defaultBranch config option — pick cms/staging so editors don't accidentally land on main.
  • A "Publish to production" action in the branch picker when the current branch is cms/* — one click to open + merge the PR (instead of leaving Keystatic).

Happy to test any of this on a live editorial site if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions