Who this is for. Anyone about to change a layout that already has content: the content modeller planning a change and the developer deploying it. After this page you can say, before you make a change, whether authors will lose anything.
The storage shape
A record does not hold its content itself. Pages, blog posts, books, units and book pages, FAQ pages and questions, custom entity records, product and category descriptions, forms and global components are versioned: their content is stored in revisions, and one revision at a time is the active revision, the one visitors see. A template reaches a value along this chain:
- the record, such as the
$pageor$postthe template receives; - its active revision, which
getActiveRevision()returns; - an area row on that revision for each layout area that has a value, pointing at the layout area by its id;
- the content row that the area row points at, holding the value.
You do not walk the chain by hand. On a versioned record every area getter reads the active revision for you: $page->getAreaText('intro') is $page->getActiveRevision()->getAreaText('intro'), and the shorthand {$page->intro} (Twig {{ page.intro }}) is the shortest way to the same value. Every saved revision keeps its own area rows, so an earlier revision still has the content it was saved with. A component placed in an area is stored with the revision whose area holds it.
The content row is the same shape for every input type. It has a column for each kind of value, and the input type's category decides which one is filled:
| Category | Where the value is in the content row |
|---|---|
| text (every editor) | The text column. A select stores its option key, a multiselect a JSON list of keys, a switch 1 or 0, a date 2026-10-19 |
| record, records | Also the text column: the id, or the ids separated by commas |
| image, file | A link to the image or file in the file manager |
| component | A component of its own, or a link to a global component |
| collection | An ordered list of collection elements, each with a position, a published flag, and a component or a global component |
The shorthand reads whichever column the category fills and returns the value in a usable form: text as text, a switch as true or false, an image, file or record as its object. The explicit getters name the column: getAreaText() reads the text column, getAreaImage() the image link, getAreaRecord() turns the stored id into a record, getAreaCollectionElements() returns the list. An empty value is not stored at all: when a record is saved, an area whose content is empty loses its area row.
What each change does to content
A template asks for content by the layout area's current name; the content is linked to the layout area's id. Every outcome below follows from those two facts.
| Change | What happens to existing content |
|---|---|
| Rewrite the template, or point the layout at another file | Nothing. The template only reads; the new one reads the same names. |
| Rename a layout area | The content stays, now under the new name. Update every template and integration that reads the area to the new name: until then, the shorthand {$page->oldName} raises "Property oldName does not exist" in Smarty and prints nothing in Twig; getAreaText('oldName') prints nothing; and an API write naming the old area is refused with a 422. |
| Switch a record to another layout | The admin copies each value into the area of the same name on the new layout. Values with no same-named area on the new layout are left out of the new revision; earlier revisions still have them. |
| Change a layout area's input type | Existing content is read with the new type. Within the same category (text to select, say) it still shows, and is checked against the new rules the next time the record is saved: a select value must then be one of the keys. Across categories (text to image) the old value reads as empty, and is left out of the next revision saved. |
| Hide a layout area | The area leaves the editing form. Templates keep reading the stored value until the record is next saved; that revision no longer has it. Hiding can be reverted with Show this area. |
| Delete a layout area | The content of every record goes with it, and cannot be recovered. Only users of the Developer type are offered the delete button for a saved area. |