Versioning & labels
Every write to an entry snapshots a new immutable version. Labels are named pointers to versions, like git branches. This is how collections model drafts, publishing, staging, and rollback.
Versions
Each POST or PATCH on an entry creates a new version (v_1, v_2, ...). A version is a frozen snapshot of the entry's data. It never changes, which makes it cacheable and safe to reference forever by id.
Floggy keeps the last 10 versions per entry. Older ones are pruned, with one exception: any version a label points at is pinned and never pruned, even if it falls outside the last 10. Remove the label and the version becomes eligible for pruning again.
Labels as branch pointers
A label is a name that points at one version. Moving a label is cheap and instant, it just re-points.
productionis special by convention: it is the published version. DefaultGETon an entry serves whateverproductionpoints at.- An entry with no
productionlabel is a draft. Default reads return404for it; you can still read it by?version=or another?label=. - Every other label is yours:
variant-a,variant-b,staging,localized-de,localized-fr, whatever your workflow needs.
Think of it as git: versions are commits, labels are branches, production is main.
Label meta
Each label carries a free-form meta JSON blob. Floggy stores and returns it verbatim and never interprets it. Use it to attach experiment weights, staging notes, translation status, or anything your pipeline reads back.
{ "version": "v_7", "meta": { "weight": 30, "locale": "de", "approvedBy": "seo-bot" } }
Publishing
Publishing is pointing production at a version. Writing a version does not do this. Nothing you write is live until a label moves.
# REST: point production at a specific version
curl -X PUT ".../collections/landing-pages/entries/<id>/labels/production" \
-H "Authorization: Bearer $FLOGGY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "version": "v_7" }'
# CLI: promote a version to production
floggy collections promote landing-pages <entryId> 7
# CLI: write and publish in one go
floggy collections set landing-pages --file entry.json --publish
Setting a label fires the label.updated webhook, so your site can revalidate on publish.
Publishing on create
A create can carry the label with it. POST /entries with { data, label: "production" } writes v_1 and points production at it in the same call, so the entry is live the moment it exists. Any label name works, so { "label": "staging" } opens a preview channel on v_1 without publishing.
Over the SDK this is label on the create input and needs @floggy/cms 0.2.1 or newer. On 0.2.0 and earlier the field is unknown, gets dropped, the create succeeds, and you are left with a draft and no error to explain it.
This is a shortcut, not a different model. It is still label-points-at-version, just done in one request instead of two, and it fires the same entry.created then label.updated webhooks.
Draft workflow
- Create an entry with no
label. It has versionv_1and noproductionlabel, so it is a draft. This is the default for every write path: REST, SDK,floggy collections set,floggy collections push. - Iterate with
PATCH. Each edit adds a version (v_2,v_3, ...). Still a draft, still invisible to default reads. - When ready, promote a version to
production. Now default reads serve it. - Keep editing. New versions accumulate;
productionstays put until you re-promote. Your live content does not change until you move the label.
Step 4 is the one that surprises people. Once an entry is published, an update is still just a version write: production stays pinned to whatever it pointed at, and your site keeps serving the old copy until you promote again. There is no auto-advance, on purpose, because that is what makes review and rollback possible. The CLI's --publish does the promote for you as part of the same command.
Rollback
Because old versions are immutable snapshots, rollback is just pointing production at an earlier version.
# See the history, with the labels on each version
floggy collections versions landing-pages <entryId>
# Roll production back to v_5
curl -X PUT ".../collections/landing-pages/entries/<id>/labels/production" \
-H "Authorization: Bearer $FLOGGY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "version": "v_5" }'
If the version you want to roll back to has been pruned (outside the last 10 and unpinned), it is gone. Pin versions you care about with a label to keep them.
Staging with labels
Use a staging label as a preview channel:
- Point
stagingat a candidate version. - Your preview build reads with
?label=staging. - When it looks right, point
productionat the same version.
The same version can carry several labels at once (staging and production, or variant-a and production after you promote a winner).
Next
- A/B testing - use arbitrary labels as experiment variants.
- API reference - the versions and labels endpoints in full.