The button never lies to you
Publishing should be the boring part of the day. Apograph tells you what is missing while you are still writing rather than after you have pressed the button — because the check in front of you runs the same validation the server will run.
For editors, and whoever owns what goes live
Four states, so nobody has to guess
Most systems show two: draft and published. That leaves the most important case — live content with edits nobody has pushed yet — looking exactly like a finished page.
- Not saved yet
A new entry nobody has committed to. Nothing exists until you save.
- Draft
Saved and being worked on. It has never been public: status is draft and there is no published date.
- Modified
Live, with unpublished edits waiting. Status is draft but a published date is set — the public still sees the previous version. This is the state that quietly causes arguments everywhere else.
- Published
Live and current. What you are looking at is what a reader gets.
Why editing something live makes it a draft again
Saving an edit to a published entry moves its status back to draft, and deliberately keeps the published date. Those two columns together carry three states rather than two: published means live and current; draft with a published date means live content with unpublished changes on top; draft without one means never published.
The consequence is that your save is unpublished working changes, while the version that was already live stays live in history until you publish again. You can accumulate several drafts over the top of a live page and then publish whichever one you meant.
One thing to know if you query the API: filtering on the published date means "last went live at", not "is currently live". Status is the column for the second question.
The readiness check is the server’s check
On a publishable type, "required" means required in order to publish. Those columns stay nullable in the database, because a half-written draft has to be saveable; the requirement is enforced at publish time instead.
That is why the panel beside the editor can be trusted: it is not a separate list of hints maintained by the front end, it is the same validation that will run on the server when you press the button. Publishing re-validates the stored row, and a failure comes back as a per-field list rather than one sentence about something being wrong.
Publish and unpublish are two directions of one transition. The live row’s status and its version timeline are written in the same transaction, so the entry and its history can never disagree about what is live — and a bulk publish selects its candidates for update and re-validates them inside one transaction, which is the only thing that closes the gap between "this draft validates" and "publish it".
Around the edges
- Publishing is its own permission
- Separate from creating and updating. Somebody can be trusted to write without being trusted to make it live, which is the distinction most permission models collapse into one.
- A required relation is counted, not guessed
- For a required many-relation the values bag holds nothing to check, so publishing counts the entry’s actual links against the stored rows. Zero links is the same refusal as an empty required field.
- Translations publish independently
- Each language is its own row with its own status, so the German page can be live while the English one is still being written.
- Editing a shared field re-validates the siblings
- If a change to a shared value would leave a published translation invalid, the whole save is refused rather than quietly invalidating a live page in another language.
The Friday question
The German page is live. The English one has an edit nobody published. Somebody asks which version the campaign links to. In most systems both rows say "published" and you find out by loading the public page. Here the English entry says Modified, the timeline shows which version is live, and the answer takes four seconds.
Questions before you rely on it
Can I schedule a post for Tuesday at nine?
Publishing happens when somebody presses the button or calls the endpoint — so a release goes out when a person is there to watch it land. Teams that want a fixed hour drive the endpoint from their own scheduler.
Can I require somebody else to approve it?
Yes, per content type. A protection rule says that entries of that type need a given number of approvals on the current version before they may go live, and by default the person who wrote that version cannot be one of them. Until somebody writes such a rule, publishing is a permission and nothing else — the publication protection page has the whole of it.
How do I roll back a bad publish?
Publish an earlier version. That marks the older version live and re-applies its content, rather than minting a copy — the timeline stays the length it was.
Does unpublishing delete anything?
No. It clears the published date and returns the entry to draft. Every version is still there.
Next
Every feature is included, free
The core is MIT licensed and every feature is in it — none of them is paid-only. Community runs free in production; a plan buys room and governance, not a different product.