Audience: Contributor
Map of the element schema system: how JSON Schema files define page elements, how the builder and API consume them, and how to change page trees or schemas safely.
See also: Page builder · Models · Page structure · Catalog · Glossary
| Audience | Start here |
|---|---|
| Content authors (visual builder) | Page builder |
| Power users debugging JSON, bindings, or actions | Page JSON track below |
| Contributors extending element schemas / editors | Extend schemas track below |
| Page | Job |
|---|---|
| Models | Persist vs runtime field contracts |
| Page structure | Stored shape, insert path, trim/persist checklist |
| Values and bindings | IValue, responsive rules, expression roots |
| Actions and validators | Closed events, action discriminators, form validators |
| Blocks and reuse | lkt-block instance shape and overrides |
| Common patterns | Copy-ready recipes only |
| Catalog | Generated type inventory |
| Schema and editors | On-disk schema + editor inference |
| Operations | Load, DbInit, codegen, scripts |
| Change playbooks | Short goal → verify → failure recipes |
| Troubleshooting | Symptom → cause → fix |
A page stores a tree of element references:
{
"title": "Home",
"children": [
{ "type": "ion-header", "children": [ /* … */ ] },
{ "type": "ion-content", "children": [ /* … */ ] }
]
}
Each node’s type string must equal some on-disk schema’s properties.type.const (for example "ion-button"). Schemas live under:
server/main/src/schema/lokakrt.com/schema/{html|ionic|lokakrt|builder}/<folder>/schema.json
The schema $id URL maps 1:1 to that file path.
Schemas are the single source of truth for:
| Concern | Driven by |
|---|---|
| Allowed node shapes | JSON Schema + AJV (page.schema.json union) |
| Default insert subtree | children.json via &def.children → DB catalog |
| Property panel widgets | Prop &def + EditorModel inference |
| Canvas / export render | &def.render + npm run generate:templates |
Prop/element training metadata is used by AI tooling; it is not required to author page JSON.
| Mechanism | Where | What it controls |
|---|---|---|
| Schema children | properties.children (sometimes root children on a few lokakrt hosts) |
AJV allow-list: leaf / unrestricted (items: true) / restricted (items.anyOf $refs) |
| Insert inside | Catalog definition.children from children.json / &def.children |
Builder drop-inside: getElementDefinition(type)?.children !== undefined (even []) |
allowed_child_elements DB column |
element table, default ["*"] |
Not synced by DbInit; builder does not consult it |
Warning: A host can allow children in AJV but have no
children.json— the builder will not offer insert-inside. Always check the Catalog columns Schema children and Insert inside separately.
children on pages, templates, or blocks (valid IElementReference JSON).AJV on save/publish is warn-only. Write valid trees anyway; do not invent keys or types because validation does not block persist.
Page JSON (import, migration, tests, binding/action debugging):
Extend schemas (new element types / editors):
Stuck? Troubleshooting.
Full list: Change playbooks. Critical rules:
type strings from the catalog.additionalProperties: false on most schemas).text element with an html prop.id, lkt_id, or builder version stamps on saved trees.lkt-block masters into instance children.schemas:page after adding element folders; MUST regenerate the wiki catalog after type inventory changes.