This page lists the data each block stores in o:data (visible through the Omeka S REST API on site_pages), the cleaning applied on save, and the variables passed to each public template. It is intended for developers scripting page content and theme authors overriding templates.
Every block cleans its data in onHydrate(), whether it comes from the page editor or the API: text is trimmed (values that are not text, such as arrays, become empty), choices outside the allowed list fall back to the default, and numbers are clamped. Links are checked when rendered: only http(s):, mailto:, tel:, site-relative (/…), #… and ?… links are output, a bare domain such as example.org/visit becomes https://example.org/visit, and anything else (for example javascript:) is dropped.
Buttons, used by Hero (up to 2) and Call to Action (up to 3), are lists of {label, url, style}; rows without a label or a URL are dropped, and style is primary, secondary or outline (default primary).
bstHero
| Key | Type | Notes |
|---|---|---|
heading |
string | Recommended; a hero with no heading, text, buttons or image renders nothing |
heading_level |
string | h2 (default) or h1 |
eyebrow, text |
string | text: blank lines separate paragraphs |
buttons |
array | Up to 2 |
image_asset_id |
int or null | |
image_position |
string | center (default), top, bottom |
scrim |
string | standard (default), strong |
height |
string | compact, standard (default), tall, screen |
align |
string | start (default), center |
Template hero.phtml receives block, heading, headingLevel, eyebrow, text, buttons, image (url, alt, asset, or null), imagePosition, scrim, height, align.
bstCallToAction
| Key | Type | Notes |
|---|---|---|
heading, text |
string | Renders nothing when there is no heading and no button |
buttons |
array | Up to 3 |
background |
string | tinted (default), accent, dark, none |
align |
string | center (default), start |
Template call-to-action.phtml receives block, heading, text, buttons, align, background.
bstStatistics
| Key | Type | Notes |
|---|---|---|
heading, intro |
string | |
items |
array | Up to 12 of {value, label, description} (strings); items with neither value nor label are dropped |
style |
string | plain (default), cards |
align |
string | center (default), start |
Template statistics.phtml receives block, heading, intro, items, style, align.
bstTimeline
| Key | Type | Notes |
|---|---|---|
heading, intro |
string | |
events |
array | Up to 50 of {date, title, text, image_asset_id, link_url, link_label}; events with neither date nor title are dropped |
Template timeline.phtml receives block, heading, intro, events (each also with image: url, alt, or null, and url: the checked link or null).
bstSearch
| Key | Type | Notes |
|---|---|---|
heading, text, label, placeholder, button_label |
string | |
target |
string | site (default, the site's search page) or items (item browse) |
suggestions |
string | One term per line, up to 12. The API also accepts a list of strings. |
Template search-box.phtml receives block, heading, text, label, placeholder, buttonLabel, action (the form's URL), suggestions (array).
cardSlider
| Key | Type | Notes |
|---|---|---|
heading |
string | |
display |
string | slider (default) or grid |
cards_visible |
int | Clamped to 1 to 6 |
autoplay |
bool | |
autoplay_interval |
int | Minimum 1000 |
cards |
array | Each: title (required, cards with an empty title are dropped), description, image_asset_id (int or null), link_url, link_label |
Template card-slider.phtml receives block, heading, cards (each card also gets image_url and image_alt from the asset), display, autoplay, autoplayInterval, cardsVisible.
itemSlider
| Key | Type | Notes |
|---|---|---|
heading |
string | |
display |
string | slider (default) or grid |
selection_mode |
string | curated or query; anything else becomes curated |
max_items |
int | Clamped to 1 to 50 |
query_item_set_id |
string or int | Empty for any item set |
query_search |
string | Passed as the search query parameter |
query_property_term, query_property_value |
string | Together, a property filter of type eq |
query_randomize |
bool | Adds sort_by=random |
display_properties |
string[] | Property terms; falls back to ['dcterms:title'] if missing |
link_to_item |
bool | |
link_label |
string | |
cards_visible, autoplay, autoplay_interval |
As for cardSlider |
Curated items are standard block attachments (o:attachment with o:item). Query mode calls api->search('items', …) with limit = max_items and site_id set to the page's site.
Template item-slider.phtml receives block, items (ItemRepresentation objects), heading, display, displayProperties, linkToItem, linkLabel, autoplay, autoplayInterval, cardsVisible, siteSlug.
tabs
| Key | Type | Notes |
|---|---|---|
heading |
string | |
display |
string | tabs (default) or accordion |
allow_multiple |
int | 1 lets several accordion sections be open |
tabs |
array | Each: label (required, tabs with an empty label are dropped), content (HTML, passed through Omeka's HTML purifier when that setting is on) |
default_tab |
int | Zero-based index; reset to 0 when out of range |
Template tabs.phtml receives block, heading, tabs, defaultTab, blockId, display, allowMultiple. Both displays share the common/blocksuite/accordion.phtml partial for the accordion markup.
Containers
Containers (tabsGroup, bstColumns, and any container registered under blocksuite.containers) store how many of the following blocks belong to them; their dividers (tab, bstColumn) split those blocks into sections.
| Layout | Key | Type | Notes |
|---|---|---|---|
tabsGroup |
span |
int | Number of following blocks inside the container, counted flatly (blocks inside nested containers count too). Minimum 0 |
tabsGroup |
heading |
string | |
tabsGroup |
display |
string | tabs (default) or accordion |
tabsGroup |
allow_multiple |
int | 1 lets several sections be open |
tab |
label |
string | Empty labels render as "Tab N" |
tab |
default |
int | 1 opens this tab (the first one wins) or section (every one marked) on load |
bstColumns |
span, heading |
As for tabsGroup |
|
bstColumns |
widths |
string | equal (default), wide-first, wide-last, wide-middle |
bstColumns |
gap |
string | small, medium (default), large |
bstColumns |
align |
string | stretch (default), start, center, end |
bstColumn |
label |
string | Editor-only note |
Containers and dividers render nothing themselves. BlockSuite\View\Helper\PageLayout builds a tree from the page's flat block list with BlockSuite\Container\BlockTree::build():
- every block uses one slot of every open container (and core block group);
- a container or core block group opens a new frame with its span;
- a divider starts a new section only in the innermost open container whose registered divider it is; anywhere else it is ignored;
- blocks inside a container before its first divider form the container's intro;
- frames close when their span is used up (innermost first), or at the end of the page if the span is too large.
The container's partial receives block, blockId, wrapperClass and wrapperStyle (the standard block classes and inline styles, including grid classes), heading, intro (HTML), and sections, a list of {block: the divider's representation, content: HTML}. For backward compatibility tabs-group.phtml also receives tabs (label, default, content) and defaultTab. A container with no sections, no intro and no heading is not rendered.
Writing pages through the API
When creating or updating a site_pages resource, list the container first, then its blocks in order, and set span to the number of blocks that follow it and belong to it, counting blocks inside nested containers. For example, two columns, the second holding a tab container with one tab:
{
"o:block": [
{ "o:layout": "bstColumns", "o:data": { "span": 6, "widths": "wide-last" } },
{ "o:layout": "bstColumn", "o:data": {} },
{ "o:layout": "html", "o:data": { "html": "<p>Founded in 1926.</p>" } },
{ "o:layout": "bstColumn", "o:data": {} },
{ "o:layout": "tabsGroup", "o:data": { "span": 2, "display": "accordion" } },
{ "o:layout": "tab", "o:data": { "label": "Today", "default": 1 } },
{ "o:layout": "html", "o:data": { "html": "<p>Open daily.</p>" } }
]
}
The page editor recomputes every span from the blocks in the drop zones whenever a block is dragged in or out and again on submit (skipping blocks marked for deletion), so hand-set values are corrected the next time the page is saved from the admin.