> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getcliq.io/llms.txt
> Use this file to discover all available pages before exploring further.

# mount_hug in depth

> How mount_hug keeps the answer, checks it, draws edit and view, and the patterns most pages need.

Hugs

`mount_hug(definition, options)` is the easy path for a hug's page: it connects to the host, keeps the answer,
checks it with the definition on every change, and draws your `edit` or `view`. The options are listed in
[Defining a hug](https://docs.getcliq.io/hugs/defining-a-hug.md); this page is about using them.

```ts theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
import { html, mount_hug, nothing } from '@getcliqio/hug-frontend';
import '@getcliqio/hug-frontend/ui';
import my_hug from '../hug';

const mounted = await mount_hug(my_hug, { initial, submit, edit, view });   // resolves once connected
```

***

## Where the answer starts

When the page opens in answer mode, the answer is the first of:

1. **the person's draft** — what they had typed, a first answer or a change to one, before reloading the page.
   The host keeps it (not the frame) in that browser tab only, until they submit, cancel the change, or the Hug ends;
   closing the tab drops it;
2. **their earlier answer** (`mine`) — when they chose **Change answer**;
3. **`initial(params)`** — or `{}`.

`initial` is merged as a partial answer, so return only what has a sensible default:

```ts theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
initial: (p) => ({ verdicts: p.documents.map((d) => ({ id: d.id, ok: true })) }),
```

## Changing the answer

`set(path, value)` changes one part. Paths use dots and brackets, and missing objects and arrays along the way are
created:

```ts theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
set('severity', 'SEV1');
set('verdicts[2].note', 'Blurry scan');
set('owner.email', 'ann@example.com');
set('verdicts[2].note', undefined);   // clear it (null works too — it's what a cleared kit field sends)
```

`replace(value)` swaps in a whole answer. Use it when the answer takes different shapes — approve or reject, an
answer or *Can't answer* — so nothing from the other shape is left behind:

```ts theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
edit: ({ value, replace }) => html`
    <cliq-choice-group label="Decision" .value=${value.decision}
        .choices=${[{ value: 'approve', label: 'Approve' }, { value: 'reject', label: 'Reject', tone: 'danger' }]}
        @change=${(e) => replace(e.detail === 'approve' ? { decision: 'approve' } : { decision: 'reject', reason: '' })}>
    </cliq-choice-group>
    ${value.decision === 'reject' ? html`<cliq-field label="Why?" multiline required .value=${value.reason}
        @change=${(e) => set('reason', e.detail)}></cliq-field>` : nothing}`,
```

After every `set` or `replace`, `mount_hug` checks the answer, tells the host whether it is valid (Submit is enabled
only then), its problems, the Submit label and the summary — and redraws.

## Conditional fields

`edit` redraws on every change, so a field that depends on another is a plain condition. Keep the same rule in the
definition, so an answer that skips the page is checked too, and clear a field when you hide it:

```ts theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
// hug.ts
values: z.object({ ok: z.boolean(), note: z.string().optional() })
    .refine((v) => v.ok || !!v.note, { path: ['note'], message: 'Say what is wrong' }),

// src/main.ts
@change=${(e) => { set('ok', e.detail === 'ok'); if (e.detail === 'ok') set('note', undefined); }}
```

## Problems

`problems` maps each path to its first problem (`''` for the answer as a whole); `problem_list` has them all. Show a
field's problem next to it — the kit's `.problem` does — and anything without a field at the top or bottom:

```ts theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
${problems['verdicts'] ? html`<p role="alert">${problems['verdicts']}</p>` : nothing}
<cliq-problems .problems=${problem_list}></cliq-problems>
```

Problems come from the definition: Zod messages, and the paths of your `refine` / `superRefine` issues
(`path: [i, 'note']` becomes `verdicts[1].note`).

## The Submit button

The Hub draws Submit, not the page. `submit` chooses its label, from the answer if you like, and its tone:

```ts theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
submit: (v) => (v.decision === 'reject' ? { label: 'Reject', tone: 'danger' } : 'Approve'),
```

At most 40 characters. Without `submit`, it says "Submit".

## The view

After the person answers — and for everyone else's answers, and once the Hug has ended — the page draws an answer
read-only. Without `view`, `mount_hug` draws one from the definition: each field's label (`.describe()`, else the
key humanized), with booleans, numbers and dates formatted for the viewer's locale, `form`'s choices by their labels,
lists as lists, and file fields as attachments. Write `view` when the answer reads better another way:

```ts theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
view: (v, { params, answer }) => html`
    <p>${v.verdicts.filter((x) => x.ok).length} of ${v.verdicts.length} OK</p>
    ${v.verdicts.map((x, i) => html`<div>${x.ok ? '✓' : '✗'} ${params.documents[i].name}${x.note ? ` — ${x.note}` : ''}</div>`)}`,
```

`answer` is the answer being shown, with `responder` and `responded_at`. Every hug must draw view mode; check yours
with `cliq hug dev --view answer.json`.

## Errors

* **Bad params** (they don't fit the definition) show an error panel listing why, instead of the editor — the Hug
  was opened wrongly, and nothing the person does can fix it.
* **An error thrown in `edit` or `view`** shows an error panel too, and is logged to the console (and to `cliq hug
  dev`'s panel).

## Anything else

`edit` receives `hug`, the [runtime API](https://docs.getcliq.io/hugs/reference/runtime-api.md), for what `mount_hug` doesn't do: read an
attachment's bytes (`hug.read_file`), open a link (`hug.open_link`), react to `progress` (`hug.on('update', …)`).
Something `edit` reads outside the answer changed — a filter, a selection? Call `mounted.redraw()` (see the
[`triage-list`](https://github.com/getcliqio/cliq/tree/main/examples/hugs/triage-list) example, which keeps its filters and selection outside the answer).

## `html`

`html` is [lit-html](https://lit.dev/docs/libraries/standalone-templates/):

| | |
| - | - |
| `${value}` | Text, escaped |
| `.prop=${v}` | Set a property (what the UI kit takes: `.value`, `.choices`, `.ref`) |
| `attr=${v}` | Set an attribute |
| `?flag=${bool}` | A boolean attribute |
| `@change=${fn}` | Listen to an event |
| `${list.map((x) => html`…`)}` | Lists |
| `${cond ? html`…` : nothing}` | Conditionals |

Don't build HTML strings — `html` escapes values, and strings wouldn't be.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.