Blocks, targeting and order
Definitions, instances, nesting and static blocks.
Definition versus instance
blocks/card.html is one reusable definition. first and second in page JSON are independent instances of that definition. Each keeps its own settings. Render settings through block.settings, not a hardcoded instance ID.
The parent declares allowed child types:
{"blocks":[{"type":"card"}],"max_blocks":6}The child needs a preset to appear in the add menu:
{"name":"Card","settings":[{"type":"text","id":"title","label":"Title","default":"New card"}],"presets":[{"name":"Card"}]}Targeting
Explicit names form an allowlist. {"type":"@theme"} allows public theme blocks. Definitions starting with _ are private and are excluded from @theme; allow them explicitly if they should be available dynamically. A private filename alone is not a static block.
Both the editor and server validate targeting. Moving a JSON instance under a parent that does not allow its type does not bypass the rules.
Dynamic order
<div class="cards"><template gs-slot="blocks"></template></div>The renderer follows block_order, not object key order. Keep all dynamic IDs unique and include them in the order list. The editor offers add, move up/down and delete. Blocks may themselves allow children using the same schema and rendering tag; do not recurse without a bounded structure.
Static blocks
<template gs-block="_signature" gs-id="signature"></template>Use literal type and ID in this syntax. A static block stays at this exact markup position; users can edit its settings but cannot reorder or delete it. The runtime renders its defaults even without saved data. Include the instance in page JSON so its controls are present from the start:
{
"title":"Home",
"sections":{
"hero":{
"type":"hero",
"blocks":{
"first":{"type":"card","settings":{"title":"Our offer"}},
"signature":{"type":"_signature","static":true}
},
"block_order":["first"]
}
},
"order":["hero"]
}Do not put signature in block_order. Do not change its type while retaining the same static declaration. Static children are rendered by their literal tag; dynamic targeting applies to the children rendered through gs-slot="blocks".
Verify a block
Add two cards and give them different titles. Reorder them, save and reload. Delete one and confirm the other retains its settings. Change the static signature text and confirm no delete/reorder actions appear. Test an empty title, a disabled checkbox and radius zero. For nested blocks, inspect the generated field paths rather than manually constructing them.