# Entity Designer agent contract (curlable)

Full SPA reference: https://gia.hub8.ai/docs/apps/entity-designer-doc  
Machine catalog (61 palette types): https://gia.hub8.ai/vibe-coding/entity-designer-catalog.json  
Golden seed: https://gia.hub8.ai/vibe-coding/golden-mini.seed.json

## Seed entity envelope

```json
{
  "name": "Demo Items",
  "schema": [ { "id": "…", "type": "textField", "options": { "label": "Item Name", "width": "half" } } ],
  "entitySettings": { "presentation": "list", "chrome": "default" },
  "renderMode": "schema",
  "customCode": ""
}
```

`name` is the **display name**. File stems use spaces → underscores.

## Naming

| Use | Example |
|---|---|
| Entity display name | `Demo Categories` |
| Metadata slug (`entityName`) | `demo_categories` (do not pass to `/metadata/{name}`) |
| Link `sourceLabel` | Exact display name `Demo Categories` |
| Data Source element Label | Entity name `Items` (not "Data Source") |

Discover live names: `GET /v1/entities/metadata` **and** `GET /v1/entities/metadata/relation-graph` (required before inventing links).

## Links

Autocomplete / link fields need both:

```json
"apiDataSource": {
  "sourceId": "entity.demo_categories",
  "sourceLabel": "Demo Categories",
  "labelField": "Category Name",
  "valueField": "Category Name"
}
```

Runtime never shows bare record ids for entity links. Filters on Data Sources use link **labels**, not ids.

## Data Source (shared load)

1. Drop palette **Data Source** (`entityDataSource`). Set unique **Label** (= binding key).
2. Configure collection / joins / filters on the Data Source only.
3. Bind consumers by Label:

| Consumer | Keys |
|---|---|
| Data Table, Chart, Map, Calendar, Pivot, List, Stack, Grid, Image List | `rowsFromEntityDataSource: true`, `entityDataSourceName: "Label"` |
| Select / Radio / … choices | `choicesFromEntityDataSource: true`, `entityDataSourceChoiceName: "Label"` |

Bindings: `${Accounts.Name}` (current repeater row), `${Accounts[0].Name}` (first row).

**Do not** put inline `apiDataSource` on chart/table/list/stack/grid/imageList consumers. Form fails at load.

Empty `${Field}` in a Data Source filter is **omitted** at fetch time.

## Layout vs repeater (agents get this wrong)

| Element | Role |
|---|---|
| `box`, `card`, `tabs`, `accordion`, `stepper` | Static layout (children once) |
| `stack` unbound | Flex toolbar/header (icon + title), **not** a repeater |
| `stack`, `grid`, `imageList` bound | Repeat template per Data Source row |
| `list` in card/box | Often static; prefer `grid` or bound `stack` for data rows |
| KPI rows | Sibling cards in a **grid** `box`, not flex row of cards |

## Auto-fill and Child Entity

| Pattern | Schema |
|---|---|
| Scalar copy on pick | `"fetchFrom": "Category.Category Name"` on Select / Autocomplete |
| Bulk import child rows | `childEntity.options.syncedRows` with `when.kind: bulkImport` |
| Row sync | `syncedRows` modes `append` / `replace` / `sync` |

**Child storage (HARD):** rows are **not** nested on the parent document. Each child doc needs `_parentId`, `_parentEntity` (registry name), `_parentField` (graph linkField), `_rowOrder`. Seed bulk without those keys = empty grid.

Clearing the driver link clears downstream auto-fill targets and bulk-import child rows.

## Hub / list

1. Canvas `entityDataSource` with Label `Items` and `apiDataSource.sourceLabel` = collection entity display name  
2. `tabularView` with `rowsFromEntityDataSource: true` and `entityDataSourceName: "Items"`

## Widths and layout

`full`, `flex`, `threeQuarters`, `twoThirds`, `half`, `third`, `quarter`, `sixth`

`layoutAlign` also accepts `space-between` / `space-around` / `space-evenly` on flex rows.

## MUI JSON (every element)

Theme and Overlay are the shell. Fill remaining MUI gaps on the element:

```json
"mui": { "dense": true, "disableGutters": true },
"sx": { "py": 0.5, "bgcolor": "background.paper" },
"slotProps": { "root": { "sx": { "px": 1 } } }
```

Prefer theme tokens. No functions or `on*` handlers. See SPA Entity Designer Doc §5.

## When to show, Rules, validation

| Key | Effect |
|---|---|
| `dependsOn` | Hide when false (Data Source: "Load when") |
| `mandatoryDependsOn` | Required when true |
| `readOnlyDependsOn` | Locked when true |
| `appearanceWhen` | **Rules** on Chip / Typography / Avatar (first match wins) |

Entity-wide submit rules: `entitySettings.validationRules: [{ id, expression, message }]`.  
Per-field: `required`, `unique`, inputType, min/max, date constraints.  
Tables: server-side sort/filter/page only.

## Actions

| `action` | Use |
|---|---|
| `applyFilters` | Refresh charts/tables from filter fields |
| `submit` / `reset` | Save or clear entity |
| `navigate` | Route or entity; optional `navigateDraftValues` |
| `openPopup` | Floating entity window |
| `callApi` | One HTTP call with entity values |
| `pay` | Razorpay checkout (Button); may save then verify |

`setFieldKey` / `setFieldValue` can run before an action (chip delete + Apply filters pattern).

## Opening view / chrome / render

`presentation`: `list` | `comfortable` | `wide` | `page` (legacy `dashboard`→wide, `mobile`→page)  
`chrome`: `default` | `bare`  
`renderMode`: `schema` | `enhanced` | `custom` (+ `customCode` for enhanced shell)

Use `bare` only for hero/landing entities, not normal CRUD.

## Display bindings

Link fields in `${…}` text resolve to **labels**, not ids. Dates format as DD/MM/YYYY (and time when present). Inside repeaters, `${Column}` = current row.

## Palette types (61)

See catalog JSON for the full list by category (inputs, selection, media, layout, display, action).  
Newer types agents often miss: `dateRangePicker` (value `{ start, end }`), `dateTimePicker`, `signatureField`, `appointmentPicker`, `mermaid`, `bpmn`, progress/icon groups, `avatarGroup`.

## Insight dashboard (seeds)

Wide presentation + date fields + Data Sources with `${From Date}` / `${To Date}` filters + 2-3 charts + full-width table.

## Apply package keys

`name`, `manifest.publishOrder`, `entities`, `menu`, `records`, `linkResolve`, `matchFields`, `options.skipEntities|skipMenu|skipRecords`

Children / masters before dependents / hubs in `publishOrder`.

## API endpoint

Cloud: `GIA_ENDPOINT=https://gia.hub8.ai/api`  
Local: `http://127.0.0.1:4000`

See apply-contract.md for success/failure shapes.

## Hard rules (summary)

| Do | Do not |
|---|---|
| Display names + `sourceLabel` | Slug-only entity lookup |
| One Data Source Label, many consumers | Inline `apiDataSource` on table/chart/list |
| `box`/`card` static; `grid`/`stack` for rows | Unbound stack as data repeater |
| Child docs with four parent keys | Nested child arrays on parent |
| Server table query | Client sort/filter/pagination |
| Seeds + HTTP apply | Hand-patch Mongo or platform code |
