LocalMode

@localmode/ui

Getting started with @localmode/ui — a shadcn registry of 100+ copy-owned, local-first AI UI components across 10 families. Install with the shadcn CLI and own the code.

@localmode/ui

LocalMode UI is a shadcn registry of 100+ copy-owned, composable AI UI components across 10 families — chat surfaces, model-download progress, device-capability gates, scored-result displays, audio I/O, vision overlays, and docked artifact canvases. They are portable to any React AI app — local-first by design, cloud-compatible by contract — and pair naturally with the recommended (optional) @localmode/core and @localmode/react hooks.

It is not an npm package. Like shadcn/ui, you install components with the shadcn CLI and own the copied code. Components are styled with shadcn/ui CSS variables, so they drop into your shadcn project and inherit your theme. The full registry and docs live at localmode.ai.

Local-first by design

Paired with the recommended on-device @localmode/react hooks, every component renders local model state — no server route, no API key, no data leaving the browser. The only network request is the one-time model download, which the components surface and gate behind an explicit action.

…and cloud-compatible by contract

The components are presentational — they render plain props and own no orchestration state — so they install with zero @localmode/* packages and work with any React AI app. Drive them from the LocalMode hooks (recommended), the Vercel AI SDK, or your own data. Local-first by design, cloud-compatible by contract.

Why a registry, not a package

LocalMode's @localmode/* npm packages give you the engine — embeddings, vector search, LLM chat, vision, audio, agents. @localmode/ui gives you the surface. Because AI UI is something you almost always want to customize (your own theme, your own copy, your own layout), the components ship as source you copy into your project rather than a black-box dependency. This is the shadcn model: you get the code, you keep the code.

Install

Add the @localmode namespace

You need a project with shadcn/ui set up (Tailwind CSS 4 with CSS variables and a components.json). Map the single-token @localmode namespace to the registry:

components.json
{
  "registries": {
    "@localmode": "https://localmode.ai/r/{name}.json"
  }
}

Install components

Install a single component, an entire family, or the whole catalog. Cross-namespace dependencies (the shared cn() util, cross-component references) resolve automatically.

# A single component
npx shadcn@latest add @localmode/ui/conversation/message

# An entire family
npx shadcn@latest add @localmode/ui/conversation

# The whole catalog (92 components)
npx shadcn@latest add @localmode/ui/all

This copies the component's .tsx into your project. Components install with zero @localmode/* packages — generic helpers are copy-owned (@localmode/ui/lib/browser-utils, @localmode/ui/lib/use-environment) — so any npm dependencies are just the component's own (e.g. lucide-react).

Wire a data source

Components are presentational — they render plain props and emit callbacks, so you can drive them from any source: the recommended on-device @localmode/react hooks, the Vercel AI SDK, or your own data. The recommended local-first pairing wires the matching @localmode/react hook and passes its state in:

chat.tsx
'use client';

import { useChat } from '@localmode/react';
import { webllm } from '@localmode/webllm';
import { Conversation } from '@/components/ui/conversation';
import { Message } from '@/components/ui/message';
import { PromptInput } from '@/components/ui/prompt-input';

const model = webllm.languageModel('Llama-3.2-1B-Instruct-q4f16_1-MLC');

export function Chat() {
  const { messages, send, isStreaming } = useChat({ model });

  return (
    <Conversation>
      {messages.map((m) => (
        <Message key={m.id} role={m.role} content={m.content} />
      ))}
      <PromptInput onSubmit={send} disabled={isStreaming} />
    </Conversation>
  );
}

The 10 families

Conversation (24)

Chat shell, streaming prompt input, reasoning, sources, tools, agent timelines, branches, and citations — the AI-native chat surface.

Local-First (24)

Model download/selection, a 160K-model Hub search browser, device-capability gates, storage quota, offline/cache status, VectorDB observability, and vector import/export panels — surfaces that exist because the model runs on-device.

Audio (10)

Voice buttons and orbs, waveform bars, TTS voice pickers, streaming-speech panels, and synced transcript viewers — STT/TTS surfaces.

Results & Insights (12)

Confidence badges, scored result bars, similarity meters, evaluation dashboards, and entity/NER displays — scored-output primitives.

Input Controls (11)

Char-limit rings, fill-mask inputs, mode pickers, language-pair selectors, parameter sliders, and slash-command palettes.

Media & Vision (6)

Image dropzones, bounding-box overlays, before/after viewers, a webcam video canvas, and result galleries — image and video I/O.

Data & Documents (5)

File dropzones, indexed-document cards, format-detection badges, category facets, and chunk-boundary visualizers — RAG and document surfaces.

Artifacts & Canvas (4)

A Claude-style docked canvas, sortable data tables, charts, and code diffs — generated output rendered beside the chat.

Security & Privacy (5)

Password-strength bars, differential-privacy controls with provenance, a passphrase gate, a lock-aware vault item card, and a lock-status badge.

DevTools (4)

Inference-queue monitor, event-log viewer, pipeline-run inspector, and model-cache table — observability primitives that render @localmode/devtools bridge snapshots.

How it composes with the packages

Each component maps to a hook you already use:

You use……to render with
useChatConversation, Message, Response, PromptInput, Branch
useAgentAgentStepTimeline, Task, Tool, ToolApproval
useSemanticSearchSources, SourceCitationList, InlineCitation, CategoryFacetList
useModelStatus / useModelLoaderModelDownloader, ModelLoadingPanel, ModelSelector
useCapabilities / useStorageQuotaDeviceBadge, CapabilityGate, DeviceCapabilityGrid, StorageMeter
useTranscribe / useSynthesizeSpeechVoiceButton, WaveformActivityBars, VoicePicker, SyncedTranscriptViewer
useClassify / useRerankConfidenceScoreBadge, ScoredResultBarList, TopResultCard
useDetectObjects / useDetectHandsMediaDropzone, BoundingBoxOverlay, VideoCanvas, ImageResultGallery
useGenerateText / useGenerateObjectArtifact, DataTableArtifact, ChartArtifact, StructuredOutputViewer

Next steps

On this page