Skip to content
Unseen UIby Stack Unseen

Getting started

Build a small React interface, then add the components you need. Unseen UI is an experimental alpha; APIs may change between releases.

1. Install from npm

The packages are public on npm under the alpha tag. Your app needs React and ReactDOM ^19.3.0, a bundler that supports CSS imports, and React types if you use TypeScript.

npm install @stackunseen/ui@alpha react@^19.3.0 react-dom@^19.3.0

@stackunseen/ui-core installs automatically as a dependency. Pin the exact version in your lockfile; the alpha tag moves with each prerelease.

Work from the source repository instead

The source repository is private. With an authorized checkout, use Node 24.13 or later within Node 24 and pnpm 11.5.0. From the repository root:

pnpm install --frozen-lockfile
pnpm build:packages
pnpm dev

Open the development site. Build the packages before starting a workspace consumer.

For the static website preview:

pnpm --filter @ai-interaction/docs build
node apps/docs/scripts/preview.mjs

Open the website preview. The preview serves the built site; rebuild the docs app after changing a page.

2. Render your first component

Import the base stylesheet once and wrap your interface in AITheme. In Next.js, this interactive example belongs in a Client Component; other React apps can use the same component.

Nothing saved yet.

This example keeps a draft and a saved name in memory. Nothing is sent or persisted. Copy it into a .tsx file and render <FirstExample /> from your app:

'use client';
import { useState } from 'react';
import { AITheme, Button, Field, Input } from '@stackunseen/ui';
import '@stackunseen/ui/styles.css';

export function FirstExample() {
  const [name, setName] = useState('');
  const [savedName, setSavedName] = useState('');
  return (
    <AITheme>
      <form
        style={{ display: 'grid', gap: 12, maxWidth: 360 }}
        onSubmit={(event) => {
          event.preventDefault();
          setSavedName(name.trim());
        }}
      >
        <Field label="Your name" required>
          <Input
            name="displayName"
            value={name}
            maxLength={80}
            onChange={(event) => setName(event.target.value)}
          />
        </Field>
        <Button type="submit">Save locally</Button>
        <p role="status">{savedName ? `Saved locally: ${savedName}` : 'Nothing saved yet.'}</p>
      </form>
    </AITheme>
  );
}

The value and callback stay in your application. To save to a server, replace the local update with your host's validation and receipt handling. Read Connect to your app before wiring tools, approvals or execution.

3. Add only the entries you need

Ordinary controls come from @stackunseen/ui. DataGrid has a separate entry and stylesheet. Keep the base CSS and AITheme from the first example.

import { DataGrid } from '@stackunseen/ui/application';
import '@stackunseen/ui/application.css';

Open the DataGrid guide for controlled rows, sorting and paging. This entry needs no additional optional peers.

Other optional entries and their dependencies

The paths below are subpaths of @stackunseen/ui. Install optional peers only for entries you import. The base React and ReactDOM peers are still required. Exact supported ranges are in the React package manifest included with the local build.

Optional @stackunseen/ui entry requirements
EntryAdditional peersExtra CSS
/theme, /status, /codeNoneNone
/markdownreact-markdown, remark-gfm, remendNone
/mathkatexkatex/dist/katex.min.css
/mermaidmermaid, dompurifyKaTeX CSS for math labels
/rich-markdownMarkdown peers, remark-math, katex, mermaid, dompurifykatex/dist/katex.min.css
/highlightshikiNone
/terminal@xterm/xterm, @xterm/addon-fit@stackunseen/ui/terminal.css
/viewport@tanstack/react-virtualNone
/layoutreact-resizable-panelsNone
/sidecar, /workspace, /uploadNoneNone

For example, a Markdown response needs these imports after installing its peers:

import { MarkdownResponse } from '@stackunseen/ui/markdown';
import '@stackunseen/ui/styles.css';

Follow each component's usage guide for its required values and callbacks. There are no /button or /icons subpaths.

4. Find your next step

Customize previews appearance, colors, density and corners. Themes and icons covers AITheme, IconsProvider and custom header/footer composition. For server responses and optional workflow examples, read Connect to your app.

Compound parts in Server Components

Compound components such as Card.Header, Sidebar.Group, Tooltip.Trigger and NavigationMenu.List are undefined when imported into a Next.js Server Component, because the client reference proxy does not carry static properties. Every part is also a top-level named export, so import those there:

import { Card, CardHeader, CardTitle, CardContent } from '@stackunseen/ui';

The property form (Card.Header) works in Client Components. Button, LinkButton, Tag, Stat, LinkCard, Card, Table, Breadcrumb and the marketing blocks render in Server Components; controls with local state, such as Select, Avatar and ToggleGroup, are Client Components and can be rendered from a Server Component.

Dark code panels on a light page

Nest a second AITheme with appearance="dark" around HighlightedCodeBlock (or any component) to render it dark inside a light page. The nested provider inherits the parent theme's colours and scopes its tokens to that subtree, and portals opened from inside it keep the same appearance.

<AITheme appearance="dark">
  <HighlightedCodeBlock code={code} language="tsx" />
</AITheme>