Journal · Bricks

How bricks store meaning, not markup

Glass-like spheres in violet and coral on a dark blue ground
Published
Authors
  • PT
    Product teamv-page
  • ET
    Engineering teamv-stack
Topics
Reading time
6 min

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.

What a page stores

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.

What a brick never stores

  • A CSS class name, so renaming a class is not a data migration.
  • A free colour: a background is one of the theme's tokens.
  • An HTML tag or a choice of component. Those belong to the code.

Tokens instead of classes

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.

Wide, flowing bands of cream, lilac and coral
One stored block, many possible looks (illustration).

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.

1. Store the page, not the address

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.

2. Leave out what cannot resolve

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.
Arched shapes in violet and peach on a pale lilac ground
A text and media brick before any token is applied (illustration).Illustration: placeholder

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

A
AcmeEngineering principle

What it costs

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.


Adding a brick

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:

  1. Could an existing brick do it with one more variant?
  2. Which of its choices are tokens, and which are content?
  3. What does it render when its image or link is missing?

Video

A brick from schema to page

A placeholder video. Like every external video on this site, it loads nothing from Vimeo until you press play.

Related

See the bricks side by side

The start page uses most of them and explains each one as you scroll.

A warm coral gradient with a dark plum glow