
From draft to published: the review flow
Four states and one review for both languages.
Journal · Bricks

A page in v-page is a list of bricks. Each brick stores what an editor chose, as data, and leaves every class name to the component. Here is why, and what it buys you.
Open a page in the CMS and you see a list of sections. In the database each one is a block of a brick: a hero, a text, a grid of cards. The block holds the copy, the images, the links and a handful of tokens, such as a variant, a spacing or a background.
One schema, no adapter. Each brick has one Effect schema. It describes exactly what Payload returns for the block, and the component receives that shape, decoded. The editor field, the renderer, the story and the validator all derive from it, so a new field is one edit.
The usual alternative is a props schema, a field map for the CMS and an adapter between them. The adapter is where data gets lost, and where the three copies drift apart.
A layout choice is a token: a variant of split, a spacing of md, an overlay of strong. The component owns how each one looks. A token an option does not use, such as an image position on a centered hero, is ignored.
A redesign touches CSS, not content. Because pages store meaning, a new look is a change to the stylesheets. Every page picks it up on its next request, and no editor has to open a section.

The same thinking keeps the database stable. Every table name is built from a short code per brick and a shared list of abbreviations that only grows, so a page of nested bricks stays within the length Postgres allows for a name.
A link to another page stores the page itself. Its address is read when the page renders, so a new slug or a new parent moves every link to it.
A link to a page that is not published, or has no address in the reader's language, is left out instead of pointing nowhere. An address typed by hand passes an allowlist first.
An internal link inside rich text reads its target's address the same way. When the target has none, the words stay plain text.
Store what the editor means. Let the component decide how it looks.

When the content holds no class names, a redesign is a stylesheet change.

Tokens are a narrower language than CSS. An editor cannot nudge one heading two pixels to the left, and that is the point. The price is a design conversation up front: every variant a page needs has to exist as a token first. That conversation is cheaper than a migration.
Some things are left out on purpose. A hero with slides would add state in the browser, so a row of slides is the carousel's job instead.
A new brick is a schema and a component in the bricks package, added to the site's brick set. The CMS derives its editor field from the set and the front end renders with it, so the brick is editable and drawn in one change.
Before you add one, a few questions are worth asking:

Video
A placeholder video. Like every external video on this site, it loads nothing from Vimeo until you press play.
The start page uses most of them and explains each one as you scroll.
