Elements#
An element (elements/{elementId}) is a reusable UI building block: fields
(the data shape of ONE placement — the same FieldSchema vocabulary as
schemas), html (a Handlebars FRAGMENT, no <html>/<head>/<body>
wrapper, binding those fields), css/js (hoisted into the page shell of
every page that places the element), sample (preview data shaped by the
fields) and a free-form category grouping tag (missing/empty = the
default group).
- ELEMENT SCOPE: an element is ONE section or component that more than one
page could place — one root, a handful of named fields. One page's own
composition is that page's per-document schema + template, not a stack of
page-specific elements. No positional keys (
t1…tN,item1_title): a list is anarrayof named objects. More than one section, or more than about 20 fields → split it; the inner pieces arecomponent: trueelements. - No literal
id="…"in a fragment (it must be safe twice on one page); an in-page anchor (a menu#hashtarget) is a bound field:id="{{anchor}}". - When asked for a COMMON UI SECTION (an FAQ, hero, testimonials, gallery,
pricing table, team grid, …), check the library FIRST
(
listStoreCollection("elements")with a["name","category","description","component"]mask) and PREFER placing a fitting element over hand-writing new markup — the library version is store-styled, maintained in one place, and edits propagate to every placement. Hand-build only when nothing fits or the user explicitly asked for a custom design, and say which of the two it was. - Content editors place an element through a
kind:"element"schema field; each placement stores its owndata({type:'element', element, data}) and the page template binds the rendered fragment as{{{ myField.html }}}— documents never embed element code. - Placements re-render with the element's CURRENT html/css/js, so an element edit propagates to EVERY page placing it — make the minimum change the request requires.
- List the library with
listStoreCollection("elements"); read one withreadStoreDocument("elements/{id}"). Edits go throughwriteStoreElement(merge-write with fields/sample validation) or plainupdateStoreDocument(merge — send only the keys you change; the element CSS must follow the CSS SCOPING rule and the fragment must be safe to repeat on one page — no colliding ids). - MODULE ELEMENTS: an element shipped by an installed store module, or one
that calls a module's
Drop{Name}runtime //m/{moduleId}/*routes, followsdrop-core://rules/module-elements—listStoreModulesthenreadModuleGuide(moduleId)before building; setmoduleon the element (writeStoreElementmodule); editing a module's own element detaches it from module updates, so duplicate it (forkOf) for a different design; the{moduleId}_runtimeelement is never written. - BEHAVIOR JS rides the element system, not standalone files — read
drop-core://rules/elementsbefore writing or moving any behavior script. Element-scoped code goes on the element'sjs(loaded only on pages that place it); a runtime shared by several elements goes insetup/elementsjs(served merged as ONE script on element-bearing pages, written viaupdateStoreDocument("setup/elements", {js})— only itsjs/csskeys are writable). Never stack store-file<script src>tags insetup/web.headTags. - When categorizing, reuse an existing
categoryvalue EXACTLY when one fits (list the elements and check the values in use) so near-duplicate groups don't fork. Category display order (order/categories) and the legacy kit provenance rows (imports/assets) insetup/elementsare managed by the admin's Elements view and module installs — never write those keys.
Translations ({{t}})#
translations is a RESERVED collection key holding the store's shared
localization strings for the {{t "group.key"}} template helper — one flat
document per group at data/{locale}/translations/{group} ({{t "cta.buy"}}
reads key buy of group doc cta, in the page's locale; optional {name}
placeholders interpolate from hash args). Humans edit them in the admin's
dedicated Localizations view; it never gets a registry row or a schema — do
NOT registerCollection it. Read/write its group documents directly like any
data documents when a template needs a key that does not exist yet; a missing
key renders the key itself, so only reference keys that exist (or create them
first). Use {{t}} for SHORT reusable UI strings (button labels, badges) —
and for every label of a SHARED schema's template that is the same on every
document (Máte dotaz?, Zobrazit další, gallery / tab / prev-next labels):
as a field, every editor would retype it on every document. Copy that differs
per document stays in document fields (an optional override field may fall
back to the key: {{#if ask_title}}{{ask_title}}{{else}}{{t "campus.ask_title"}}{{/if}}).