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

# Customization

> Adapt AomiWidget with props, themes, source components, or the headless React library while preserving its runtime behavior.

Start with `AomiWidget`, then take ownership of more of the interface only when your product needs it.

## Choose your customization level

| Level            | You own                        | Aomi provides                        |
| ---------------- | ------------------------------ | ------------------------------------ |
| Widget props     | Placement and visible controls | Complete UI, runtime, and wallets    |
| Themes           | Brand colors and visual tokens | Component structure and behavior     |
| `AomiFrame`      | Component composition          | Chat, threads, and wallet components |
| shadcn source    | The copied component source    | A production starting point          |
| Headless library | The complete interface         | State, runtime, and React hooks      |

## Configure AomiWidget

Use presentation props to fit the widget into a page, panel, or modal.

```tsx theme={null}
<AomiWidget
  applicationId="123"
  apiUrl="https://chat.aomi.dev"
  auth={{ kind: "browser_wallet" }}
  width="100%"
  height="min(780px, calc(100dvh - 160px))"
  showSidebar
  showHeader
  walletPosition="footer"
/>
```

| Prop                 | Purpose                                                                  |
| -------------------- | ------------------------------------------------------------------------ |
| `width`, `height`    | Size the widget container                                                |
| `className`, `style` | Add application-specific layout styles                                   |
| `showSidebar`        | Show or hide thread navigation                                           |
| `showHeader`         | Show or hide the widget header                                           |
| `walletPosition`     | Place the wallet control in the header or footer; pass `null` to hide it |
| `wallets`            | Limit presented wallets, chains, and networks                            |
| `persistThread`      | Restore the active thread after a reload                                 |

These props change presentation. The Application ID selects the deployed App; action review and wallet execution remain visible client responsibilities.

## Apply themes and styles

Import the default stylesheet once:

```tsx theme={null}
import "@aomi-labs/widget-lib/styles.css";
```

Then override its CSS variables in your application stylesheet. Keep transaction warnings, fees, owner addresses, and confirmation states visually distinct when changing colors.

## Compose with AomiFrame

Use the compound API when the standard widget layout is close to what you need, but you want to rearrange its sections.

```tsx theme={null}
import { AomiFrame } from "@aomi-labs/widget-lib";

<AomiFrame.Root
  backendUrl="https://chat.aomi.dev"
  applicationId="123"
  height="720px"
  showSidebar={false}
>
  <AomiFrame.Header showSidebarTrigger={false} />
  <AomiFrame.Composer
    withControl
    welcomeTitle="How can I help?"
  />
</AomiFrame.Root>;
```

`AomiFrame` provides the chat surface and runtime. If you use it outside `AomiWidget`, your application must supply the surrounding authentication and account integration.

## Own the source with shadcn

Copy the widget components into your repository when you need to change markup or component behavior:

```bash theme={null}
npx shadcn add https://aomi.dev/r/aomi-widget.json
```

Copied components become application code. Review registry updates before overwriting local changes.

## Build a headless UI

Choose the headless library when props, themes, composition, and copied components are not enough. Aomi continues to provide thread, chat, user, event, notification, and wallet-request state. You provide every visible interaction.

### Install the library

```bash theme={null}
npm install @aomi-labs/react @assistant-ui/react
```

### Add the runtime provider

```tsx theme={null}
import { AomiRuntimeProvider } from "@aomi-labs/react";

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <AomiRuntimeProvider
      backendUrl="https://chat.aomi.dev"
      applicationId="123"
    >
      {children}
    </AomiRuntimeProvider>
  );
}
```

### Your responsibilities

A headless interface must provide:

* Thread navigation and message rendering.
* Composer, streaming, cancellation, and error states.
* Wallet connection and network selection.
* Transaction-call and fee disclosure.
* Explicit approval and rejection controls.
* Owner and network validation before signing.
* Submitted, confirmed, expired, and failed operation states.

<Warning>
  Returning a generic transaction result is not enough. Your interface must narrow each action by `action.request.kind`, show the exact request, and return the result that kind expects. Prefer `AomiWidget` unless you need to own the full approval experience.
</Warning>

## Hooks

All hooks must run beneath `AomiRuntimeProvider`.

### Chat and threads

| Hook                       | Purpose                                                         |
| -------------------------- | --------------------------------------------------------------- |
| `useAomiRuntime`           | Unified chat, thread, user, notification, event, and wallet API |
| `useThreadContext`         | Low-level thread state and operations                           |
| `useCurrentThreadMetadata` | Metadata for the active thread                                  |

Read active-thread messages with `useAomiRuntime().getMessages()`.

### User and wallet controls

| Hook                  | Purpose                                           |
| --------------------- | ------------------------------------------------- |
| `useUser`             | Canonical user and wallet state                   |
| `useControl`          | Combined App, model, API-key, and secret controls |
| `useApiKey`           | API-key state and actions                         |
| `useAuthEndpoints`    | Available Apps and models                         |
| `usePerThreadControl` | Per-thread App and model selection                |

### Events and notifications

| Hook              | Purpose                                     |
| ----------------- | ------------------------------------------- |
| `useNotification` | Notice, success, wallet, and error messages |

Read ordered backend events from `useAomiRuntime().events` and the active lifecycle from `turnState`. `pendingActions` contains canonical Actions; narrow on `action.request.kind` before reading its payload. Use the exported TypeScript types as the source of truth for complete signatures and payloads.

## Complete custom UI example

This starter owns message rendering, the composer, cancellation, and the visible wallet-request count:

```tsx theme={null}
"use client";

import { useState, type FormEvent } from "react";
import { useAomiRuntime } from "@aomi-labs/react";

export function CustomChat() {
  const [input, setInput] = useState("");
  const {
    currentThreadId,
    getMessages,
    sendMessage,
    isRunning,
    cancelGeneration,
    pendingActions,
  } = useAomiRuntime();

  const messages = getMessages(currentThreadId);

  async function submit(event: FormEvent) {
    event.preventDefault();
    const text = input.trim();
    if (!text || isRunning) return;
    setInput("");
    await sendMessage(text);
  }

  return (
    <main>
      <section aria-live="polite">
        {messages.map((message, index) => (
          <article key={index} data-role={message.role}>
            <strong>{message.role}</strong>
          </article>
        ))}
      </section>

      <form onSubmit={submit}>
        <input
          value={input}
          onChange={(event) => setInput(event.target.value)}
          disabled={isRunning}
        />
        {isRunning ? (
          <button type="button" onClick={cancelGeneration}>Stop</button>
        ) : (
          <button type="submit">Send</button>
        )}
      </form>

      <p>{pendingActions.length} actions need review</p>
    </main>
  );
}
```

Add an approval component for every action kind your App can produce. Show the calls, signatures, owner, network, simulation evidence, and terminal status available on the request.
