Page structure
Mark the parts of your page so tools can find, show and render them
Mark the parts of your page with a few HTML attributes, and the Inspect panel in anfra serve shows them as a tree: hover a part to see it on the page, click it to scroll there, or pick a spot on the page to find its part in the tree. The same marks name the parts that Anfra.render() can save as a picture, and they give you a handle for a part that you can paste into a request to a coding agent.
The markup is optional, and it costs one attribute per part, so mark every part your page draws.
Marking the parts
<main data-anfra-container="page" data-anfra-label="Overview">
<div data-anfra-container="controls" data-anfra-label="Controls">
<label data-anfra-block="region-picker" data-anfra-control="region">…</label>
</div>
<div data-anfra-container="kpis">
<div data-anfra-block="revenue" data-anfra-query="totals">…</div>
<div data-anfra-block="orders" data-anfra-query="totals">…</div>
</div>
<section data-anfra-block="trend" data-anfra-label="Revenue over time">
<div id="trend-chart" data-anfra-query="trend"></div>
<select data-anfra-control="grain"></select>
</section>
</main>Here revenue and orders are two blocks drawn by the same query, and the trend block holds both its chart and the control that belongs to it.
| Attribute | On | Means |
|---|---|---|
data-anfra-container="<id>" | Any element | A container, which can hold anything. |
data-anfra-block="<id>" | Any element | A block: the smallest part a reader sees as one thing. It holds no container or block. |
data-anfra-label="<text>" | A container or block | Its name in the tree and in a picture's filename. Optional. |
data-anfra-query="<name>" | Any element | This element is drawn by that query. Separate several names with spaces. On a block's own element, it means the whole block is drawn by that query. |
data-anfra-control="<name>" | Any element | The same, for a filter or date drill. |
data-anfra-render="skip" | Any element | Left out of every picture, with everything it holds, such as a download button or a spinner. |
Rules
- Ids are required, and unique per kind in the page.
- Query and control names are the ones you gave
createQuery,createFilterandcreateDateDrill. In a page that creates several apps, write<index>/<name>with the app's index, such as1/trend. A bare name means app 0. - Every query and control marker sits in a block, or on a block's own element. A control that stands alone, such as a filter in a toolbar, gets a block of its own. A control that belongs to one chart, such as a grain switch in the chart's header, goes in that chart's block.
- Mistakes such as an unknown name, a duplicate id, or a block inside a block are shown on the part in the Inspect panel's tree, never thrown.
- Elements your page adds later, such as a table drawn on the first result, appear once they exist.
- Nothing reads the markup until a tool needs it: the Inspect panel while it is open, or
Anfra.render()when it looks up a block or container. Marking every part costs your page nothing at load.
Finding a query on the page
query.locate() and control.locate() scroll to the elements marked with that query or control, and highlight them for a moment. Use them for a "find on page" button of your own. They return false when nothing is marked yet, and never throw.
Handles for a coding agent
When you pick a part in the Inspect panel, you can copy its handle, such as [Revenue over time](data-anfra-block="trend"), and paste it into a request to a coding agent. The part in parentheses is the attribute as written in the file, so the agent can search for it and change the element you mean.
Related
- Render: save a block, a container or the page as a picture.
- Build a data app: the Inspect panel.