"description":"Describes a dashboard page configuration with global filters and rows of visualizations.",
"markdownDescription":"AI guidance: a dashboard belongs to a page with `type: \"dashboard\"`. It contains one or more rows; each row contains chart, list, or numberContainer visualizations. Use visualization `entityName` to select data for chart/list items. Use numberContainer for KPI tiles, charts for grouped aggregations, and lists for recent/top records.",
"description":"Describes a dashboard page configuration with global filters and a flat list of visualizations.",
"markdownDescription":"AI guidance: a dashboard belongs to a page with `type: \"dashboard\"`. It contains a flat `visualizations` list; each visualization carries its grid position via `row`, `order`, and `width`. Rows are derived at render time by grouping visualizations that share the same zero-based `row`. Use visualization `entityName` to select data for chart/list items. Use numberContainer for KPI tiles, charts for grouped aggregations, and lists for recent/top records.",
"description":"Describes one row in the dashboard layout grid. Each row contains one or two visualization items.",
"markdownDescription":"AI guidance: organize dashboard visualizations into rows by visual importance. Use one item for a full-width chart/list/number panel, and two items when related visualizations should be displayed side by side. Do not put more than two visualizations in a row; create another row instead.",
"type":"object",
"properties":{
"items":{
"type":"array",
"description":"Visualization items in this row. Use one item for full-width content or two items for a two-column row.",
"description":"A single visualization element in a dashboard row: chart, list, or number container.",
"description":"A single visualization element in a dashboard: chart, list, or number container. Positioned on the grid via row, order, and width.",
"markdownDescription":"AI guidance: set `type` and then provide the matching payload: `chart` for type chart, `list` for type list, or `numberContainer` for type numberContainer. Do not populate unrelated payloads. Chart and list visualizations require `entityName`; number containers define entityName per KPI item.",
"type":"object",
"properties":{
@ -23,6 +23,16 @@
"type":["string","null"],
"description":"Optional description text. Can be shown inline or as tooltip depending on showDescriptionAsTooltip."
},
"row":{
"type":"integer",
"description":"Zero-based visual row index inside the dashboard grid. Visualizations sharing the same row are rendered side-by-side.",
"minimum":0,
"default":0
},
"order":{
"type":["integer","null"],
"description":"Order of the visualization inside its row. When omitted, array order is used."
"description":"Describes a named create/edit form definition bound to one entity.",
"markdownDescription":"AI guidance: a form is referenced by page `formName`, `createFormName`, or `editFormName`. Keep `entityName` aligned with the page entityName. Define all fields in `fields`, then place every visible field in `layout.tabs[].groups[].rows[].cells[]` by field id. Use form `rules` for conditional visibility/enabled state; use entity validators for core data validation.",
"markdownDescription":"AI guidance: a form is referenced by page `formName`, `createFormName`, or `editFormName`. Keep `entityName` aligned with the page entityName. Define all fields in `fields`, then place every visible field in `layout.tabs[].groups[].fields[]` by field id (each placement carries `row`, `colSpan`, and `colStart`). Use form `rules` for conditional visibility/enabled state; use entity validators for core data validation.",
"type":"object",
"properties":{
"$schema":{
@ -34,7 +34,7 @@
},
"layout":{
"$ref":"form-layout-descriptor.schema.json",
"description":"Visual layout for the fields. Every layout cell fieldId must refer to a field in fields."
"description":"Visual layout for the fields. Every layout placement fieldId must refer to a field in fields."
"description":"Describes a single field in a form. A field may be bound to an entity property or unbound for computed/display-only UI.",
"markdownDescription":"AI guidance: use a stable camelCase `id` for each field. For ordinary data entry, set `binding` to an entity property and choose a field `type` compatible with that property. For enum selects, set `type: \"select\"` and `enumType`. For FK lookups, use `type: \"lookup\"` and bind to the FK property. Put fields into layout cells by id.",
"markdownDescription":"AI guidance: use a stable camelCase `id` for each field. For ordinary data entry, set `binding` to an entity property and choose a field `type` compatible with that property. For enum selects, set `type: \"select\"` and `enumType`. For FK lookups, use `type: \"lookup\"` and bind to the FK property. Place fields into the layout by adding a placement that references this id in a group's `fields`.",
"type":"object",
"properties":{
"id":{
"type":"string",
"description":"Unique identifier for this field within the form. Prefer camelCase, for example 'title' or 'customerId'. Layout cells and rules reference this id.",
"description":"Unique identifier for this field within the form. Prefer camelCase, for example 'title' or 'customerId'. Layout placements and rules reference this id.",
"description":"Describes the visual layout of a form as tabs, groups, rows, and field cells.",
"markdownDescription":"AI guidance: the layout is a tree: tabs -> groups -> rows -> cells. Each cell `fieldId` must reference a field from the form's `fields` array. Use `colSpan` 4 for full-width fields, 2+2 for two columns, or 1+1+1+1 for four compact controls. The total effective width in a row should not exceed 4.",
"description":"Describes the visual layout of a form as tabs and groups. Each group holds a flat list of field placements positioned on a 4-column grid.",
"markdownDescription":"AI guidance: the layout is a tree: tabs -> groups -> fields. The stored schema is flat (no row/cell wrappers): each placement carries `row`, `colSpan`, and `colStart`. Rows are derived at render time by grouping placements that share the same zero-based `row`. Each placement `fieldId` must reference a field from the form's `fields` array. Use `colSpan` 4 for full-width fields, 2+2 for two columns (colStart 1 and 3), or 1+1+1+1 for four compact controls. The sum of `colSpan` values within a row should not exceed 4.",
"type":"object",
"properties":{
"tabs":{
@ -28,6 +28,10 @@
"description":"Whether this is the default tab. The designer uses the default tab as the safe target for orphaned fields.",
"default":false
},
"order":{
"type":"integer",
"description":"Optional display order for this tab. When omitted, array order is used."
},
"groups":{
"type":"array",
"description":"Ordered list of groups within this tab. Use one default group for simple forms.",
@ -49,49 +53,47 @@
"description":"Whether this is the default group. The designer uses the default group as the safe target for orphaned fields.",
"default":false
},
"rows":{
"order":{
"type":"integer",
"description":"Optional display order for this group. When omitted, array order is used."
},
"fields":{
"type":"array",
"description":"Ordered list of layout rows; each row contains one or more cells placed side-by-side.",
"description":"Flat list of field placements in this group. Each placement positions a single field on the 4-column grid via row, colSpan, and colStart.",
"items":{
"type":"object",
"properties":{
"cells":{
"type":"array",
"description":"Fields placed side-by-side in this row. The sum of colSpan values should not exceed 4.",
"minItems":1,
"items":{
"type":"object",
"properties":{
"fieldId":{
"type":"string",
"description":"Reference to a field id in the form's fields array. Every field shown in the layout needs a matching field descriptor.",
"minLength":1
},
"colSpan":{
"type":"integer",
"description":"Number of grid columns this field spans from 1 to 4. Use 4 for full-width fields.",
"minimum":1,
"maximum":4,
"default":4
},
"colStart":{
"type":["integer","null"],
"description":"Starting grid column from 1 to 4. Omit or null to auto-place after the previous cell.",
"minimum":1,
"maximum":4
}
},
"required":["fieldId"],
"additionalProperties":false
}
"fieldId":{
"type":"string",
"description":"Reference to a field id in the form's fields array. Every field shown in the layout needs a matching field descriptor.",
"minLength":1
},
"row":{
"type":"integer",
"description":"Zero-based visual row index inside the group. Placements sharing the same row are rendered side-by-side.",
"minimum":0,
"default":0
},
"colSpan":{
"type":"integer",
"description":"Number of grid columns this field spans from 1 to 4. Use 4 for full-width fields.",
"minimum":1,
"maximum":4,
"default":4
},
"colStart":{
"type":["integer","null"],
"description":"Starting grid column from 1 to 4. Omit or null to auto-place after the previous placement in the same row.",
"description":"The runtime page renderer to use. Prefer lower-case values in descriptor JSON; PascalCase aliases are accepted for compatibility.",
"markdownDescription":"`dataGrid` renders searchable/filterable tabular CRUD for an entity. `kanban` renders grouped cards and requires `groupByProperty`. `calendar` renders entity records on a calendar and requires `calendarStartProperty`. `gallery` renders visual cards and may use `galleryImageProperty`. `form` renders a standalone create/edit form page and requires `formName`. `dashboard` renders dashboard rows/visualizations and requires `dashboard`.",
"markdownDescription":"`dataGrid` renders searchable/filterable tabular CRUD for an entity. `kanban` renders grouped cards and requires `groupByProperty`. `calendar` renders entity records on a calendar and requires `calendarStartProperty`. `gallery` renders visual cards and may use `galleryImageProperty`. `form` renders a standalone create/edit form page and requires `formName`. `dashboard` renders a flat list of dashboard visualizations and requires `dashboard`.",