# Structured Output Viewer

Structured Output Viewer [#structured-output-viewer]

The **StructuredOutputViewer** extends `Response` for `useGenerateObject`. It pretty-prints the extracted JSON in a scrollable block, pairs it with an independently-usable `InferenceStats` footer (token count, wall-clock duration, attempt/retry count), and offers a navigable typed `SchemaTree` view so output can be inspected both as data and as its schema shape.

Preview [#preview]

```tsx
'use client';

/**
 * @file structured-output-viewer-demo.tsx
 * @description Docs preview for `StructuredOutputViewer`. Shows a generated
 * object with JSON + schema-tree tabs and an inference-stats footer.
 */
import { StructuredOutputViewer } from '@/components/structured-output-viewer';

const OBJECT = {
  invoice: {
    number: 'INV-2042',
    date: '2026-05-31',
    total: 1280.5,
    currency: 'USD',
    lineItems: [
      { description: 'Pro plan (annual)', amount: 1200 },
      { description: 'Support add-on', amount: 80.5 },
    ],
    paid: false,
  },
};

export default function StructuredOutputViewerDemo() {
  return (
    <div className="w-full max-w-xl">
      <StructuredOutputViewer
        object={OBJECT}
        usage={{ totalTokens: 312 }}
        durationMs={1840}
        attempts={1}
      />
    </div>
  );
}
```

Installation [#installation]

```bash
npx shadcn@latest add @localmode/ui/conversation/structured-output-viewer
```

Data source & dependencies [#data-source--dependencies]

**Data source:** renders the parsed object + usage you pass — works with any backend. Recommended producer: `useGenerateObject` result + usage from `@localmode/react` (on-device, optional).

* `clsx` + `tailwind-merge` — via the shared `cn()` util (installed automatically as a registry dependency)

Files installed [#files-installed]

* `structured-output-viewer.tsx` — `StructuredOutputViewer`, `InferenceStats`, `SchemaTree`
* `lib/utils.ts` — the `cn()` helper (if not already present)

Props [#props]

**StructuredOutputViewer**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `object` | `unknown` | — | **Required.** The generated object (from `useGenerateObject`). |
| `usage` | `object` | — | Token usage to surface in the footer. |
| `durationMs` | `number` | — | Wall-clock duration in milliseconds. |
| `attempts` | `number` | — | Number of attempts/retries. |

Examples [#examples]

Render a generated object [#render-a-generated-object]

```tsx
import { useGenerateObject } from '@localmode/react';
import { StructuredOutputViewer } from '@/components/structured-output-viewer';

const { data } = useGenerateObject({ model, schema });

{data && <StructuredOutputViewer object={data.object} usage={data.usage} durationMs={elapsed} />}
```

Customization [#customization]

`InferenceStats` is exported separately — drop it beneath any `useGenerateText` result for the same tokens/duration footer. `SchemaTree` derives its tree from the value's runtime shape; swap it to read your Zod/JSON schema directly if you prefer the declared shape.

These primitives are presentational and hook-driven: they render props and emit callbacks, holding only local view state. The orchestration state (e.g. `useGenerateObject`) lives in your app. Every surface uses shadcn/ui CSS-variable utilities, so it inherits your theme — restyle the copied file freely.