# Content Item Types All `content.json` files use an `items` array of typed objects. Every object has a `type` field; all other fields depend on the type. Optional fields are marked with `?`. Token substitution is available in most string fields: any `%TOKEN%` placeholder is replaced with the corresponding value. Where noted, a string that resolves to a JSON array or object is automatically parsed back into the appropriate structure. --- ## Access control Any item (and any table column or row action) can carry a `client_requirement` field. Items whose requirement is not satisfied are omitted entirely from the rendered output. Roles are ranked from lowest to highest: | Rank | Role | Description | |------|------|-------------| | 3 | `manager` | Superuser; can manage accounts and administrators | | 2 | `administrator` | Full configuration access | | 1 | `viewer` | Read-only authenticated user | | 0 | `nothing` | Unauthenticated (no session) | The value is a role name with a suffix that controls the comparison: | Suffix | Meaning | |--------|---------| | `+` | Client rank must be greater than or equal to the named role | | `=` | Client rank must equal the named role exactly | | `-` | Client rank must be less than or equal to the named role | Possible values for `client_requirement` field: | Value | Meaning | |----------|-------------| | `client_is_manager=` | Client must be manager | | `client_is_manager-` | Client must be manager or lower | | `client_is_administrator+` | Client must be administrator or higher | | `client_is_administrator=` | Client must be administrator | | `client_is_administrator-` | Client must be administrator or lower | | `client_is_viewer+` | Client must be viewer or higher | | `client_is_viewer=` | Client must be viewer | | `client_is_viewer-` | Client must be viewer or lower | | `client_is_nothing+` | Client may be anybody (logged in or not logged in) | | `client_is_nothing=` | Client must be nothing (not logged in) | Example: ```json { "client_requirement": "client_is_administrator+", "type": "card", "items": [] } ``` --- ## Layout / structure ### `h1` ```json { "type": "h1", "text": "Page Title" } ``` Renders as `

`. --- ### `hr` ```json { "type": "hr" } ``` Full-width horizontal rule. --- ### `p` ```json { "type": "p", "text": "Introductory text.", "link?": { "text": "Click here", "action": "/some-path" } } ``` Paragraph with an optional inline link appended after the text. --- ### `spacer` ```json { "type": "spacer" } ``` Blank vertical space (`
`). --- ### `header_page_title` ```json { "type": "header_page_title", "items": [ ... ] } ``` Wraps children in the page header div. Typically contains `h1` and toolbar buttons. --- ### `section` ```json { "type": "section", "items": [ ... ] } ``` Generic section wrapper (`
`). --- ### `auth_wrapper` ```json { "type": "auth_wrapper", "items": [ ... ] } ``` Full-page centering wrapper for login/auth pages. --- ### `auth_card` ```json { "type": "auth_card", "items": [ ... ] } ``` Contained card used on auth pages. --- ### `card` ```json { "type": "card", "label?": "Card Title", "id?": "my-card-id", "hidden?": true, "items": [ ... ] } ``` General-purpose card with an optional header label. Setting `hidden: true` renders the card with the `hidden` attribute, which is used for `js_edit` reveal targets. The `id` attribute wires it up as a `js_edit` target. --- ### `grid` ```json { "type": "grid", "rows": [ { "cells": [ { "type": "grid_label", ... }, { "type": "grid_value", ... } ] } ] } ``` Two-column info grid. Each row contains `cells` rendered inline. --- ### `grid_label` ```json { "type": "grid_label", "text": "Label" } ``` Label cell in an info grid row. --- ### `grid_value` ```json { "type": "grid_value", "text": "%TOKEN%" } ``` Value cell in an info grid row. Token substitution applies. --- ### `raw_html` ```json { "type": "raw_html", "html": "Some markup" } ``` Injects raw HTML without escaping. Token substitution applies. Use sparingly. --- ## Buttons All button types share these optional fields: | Field | Meaning | |-------|---------| | `text` | Button label | | `class?` | Extra CSS classes appended to the default | | `disabled?` | Token expression; disables button if truthy (not `"false"` / `"0"`) | ### `button_primary` / `button_secondary` / `button_danger` / `button_ghost` ```json { "type": "button_primary", "text": "Save", "action?": "/some/path", "method?": "post", "formaction?": "/alternate/path", "disabled?": "%SOME_TOKEN%" } ``` - No `action`: renders `