--- name: homarr-custom-widget description: Author, validate, preview, test, install, or configure API-backed Homarr Custom JSX v2 widgets. --- # Homarr Custom Widget Author requested widgets with release context; validate, test, persist, and return artifacts. - Read primary API docs when missing/changed. Samples and successful previews are binding; load only needed schema, runtime, security, or component context. - Batch unknown component searches/details. `contextAlreadyLoaded` reuses context; `phaseComplete` advances. Stop only for genuine provider/model, lifecycle-service, or workbench-closure failure. - Community widgets use `customWidget_workshopSearch`, `customWidget_workshopGet`, and `customWidget_workshopInstall`; configure and persist. Return one fenced `json` block with the complete definition; keep evidence prose outside it. The definition has keyed `sources`, `requests`, `template`, and optional `options`; actions are requests with `kind: "action"`. - `sources.default` is required. HTTP has `baseUrl`, `networkScope`, and credential-free `auth`; localhost/loopback requires `networkScope: "loopback"`; never widen an explicit scope. Saved sources use `type: "integration"`/`integrationKind`; Homarr holds credentials. - Saved integrations: discover kinds/full-access entries with `integration_getKinds`/`integration_all`, bind `integrationId` before preview, omit URL/auth, and keep non-GET requests as actions. - Paths are slash-prefixed: strings use `{option:name}`/`{param:name}`; query/body uses `{"$option":"name"}`/`{"$param":"name"}`. Loads use `trigger: "load"`; manual helpers use `trigger: "manual"`. - Actions stay manual; preserve `confirmation`, `permission`, and `invalidates`; DELETE requires full permission/confirmation. `$param` is manual-only; `$option` may drive loads. - Load data.requestId/status.requestId with RefreshButton; status.requestId?.ok === false is error. Manual SubFetch never populates data/status; its child receives (result, metadata) and renders its fields. - Options have `label`, `control`, `default`; installation config is `options.name`, never `inputs`. Request-bound TextInput, Select, NumberInput, Pagination use literal `bind` + default and manual `SubFetch params` map `inputs.` to `$param`. Dependent pagination uses `defaultValue={1}`/`resetKey={inputs.query}`. Remove controls without an option/request/helper; guard arrays/nested with `??`; preserve documented timezone values; use UTC only when the contract says UTC. - Templates are one expression: no imports, hooks, refs, raw HTML/events, browser requests, eval, recursion, IIFEs, statement blocks, or arbitrary functions. Use registered component names; `Icon` may alias `TablerIcon`. Keep hierarchy, theme tokens, useful states, and narrow/wide layouts purposeful. ## Bounded lifecycle 1. Build a credential-free definition from request, verified context, and sample. Preserve a migration's API path, method, body, options, and behavior; omit unknown requests rather than guessing. 2. Send the coherent complete definition directly to `customWidget_previewCreate`; it validates both manifest and JSX. Use `customWidget_validateTemplate` only for isolated JSX diagnostics, never as a preview prerequisite. Use `customWidget_previewReviseTemplate` for JSX-only corrections after a preview exists. In the Assistant wrapper, multiline JSX uses `templateLines` and preview creation receives the complete definition. 3. Test every returned query/simulated action once, batching independent queries. On a concrete schema/preview error, fix only that field and retry `customWidget_previewCreate` with the corrected definition; use `customWidget_previewReviseTemplate` only for JSX errors after a preview exists. Stop only for genuine provider/model, lifecycle-service, or workbench-closure failure. 4. If `previewCreate` used `definitionId`, persist with `customWidget_updateFromPreview`; otherwise use `customWidget_createFromPreview`. Follow create `nextAction` once. Configure credentials in Homarr; never repeat plaintext secrets. ## Delivery Report actual lifecycle results. If unavailable, add one post-artifact `Unverified:` line naming missing validation, preview, renderer, or persistence. Never claim rendering/persistence from schema checks.