Structural editing
Structural editing is a schema-controlled operation, not arbitrary DOM manipulation. A structural command identifies a section by its stable section ID and asks the framework to add, move, remove, or duplicate it. The framework reads the component definition and rejects an operation that its structure or placement policy does not allow.
The current applyStructuralMutation runtime helper supports:
addfrom the component’s schema-validdefaultContentat an approved document position;movewithin the existing document order;removewhen the component is removable;duplicateonly when the component is duplicable and below its instance limit.create-row,move-row,update-row, andremove-rowfor one-level responsive canvas layout;addandmoveinto an approved row through an optionalparentId.
For add, the caller supplies a new stable section ID, component type, destination index, and optional row parent. The runtime derives a stable slot ID, uses the first developer-approved layout variant, requires placement in the matching main or row region, applies the tighter of structure.maxInstances and placement.maxInstances, and validates the complete result with pageDocumentSchema.
It rejects unknown section IDs or component types, invalid destinations, duplicate IDs, locked sections, disallowed placement, and instance-limit violations before persistence. The caller still performs authorization, optimistic version checking, audit logging, and draft persistence.
The Morning Bell sidebar exposes this contract as an approved component palette. Editors may click or tap an item to append it, or drag it between existing sections. Existing movable sections expose a drag handle. A coral insertion line previews the destination, but the browser never makes the dropped DOM authoritative: it submits the structural mutation and replaces the canvas with a fresh server-rendered draft after success.
The palette also offers a Layout row. A row owns only responsive geometry: one to four desktop/tablet columns, a fixed one-column mobile stack, and a bounded gap. It may contain up to four normal component references. A row never owns component content, cannot contain another row, and removing it unwraps its children rather than deleting them. Stable IDs let the server detect unknown, duplicate, missing, or colliding references.
Content sections may move, be removed, or be duplicated up to their developer-defined limit. Hero may move or be removed but cannot be duplicated or placed in a row, and its palette entry is disabled when one instance already exists. More granular named theme regions and required-slot replacement decisions remain theme-migration concerns.