Getting StartedHerald UI

Guide

Getting Started

Herald is a kit for building a whole AI OS, not a single chat widget. The fastest path: start with the shell, drop in the chat surface, wire your backend, then add surfaces. Here's the shape it takes.

1. Start with the shell

Every AI OS needs a frame — a nav rail, a topbar, a content area. AppShell is that frame, data-driven: pass your nav and it renders.

import { AppShell, Sidebar, Topbar } from "@/blocks/app-shell"
import { MessageSquare, Boxes } from "lucide-react"

export function Cockpit({ children }) {
  return (
    <AppShell
      sidebar={
        <Sidebar
          groups={[
            { label: "Workspace", items: [
              { label: "Chat", icon: <MessageSquare />, href: "/chat", active: true },
              { label: "Fleet", icon: <Boxes />, href: "/fleet" },
            ]},
          ]}
        />
      }
      header={<Topbar>Chat</Topbar>}
    >
      {children}
    </AppShell>
  )
}

2. Drop in the chat surface

ChatPanel is a full, drop-in chat surface — Thread + Composer + model picker — driven by a typed parts[] message model (text, reasoning, tool calls, images).

import { ChatPanel } from "@/blocks/chat-panel"

<ChatPanel
  messages={messages}
  draft={draft}
  onDraftChange={setDraft}
  onSend={send}
  isStreaming={isStreaming}
  models={models}
  model={model}
  onModelChange={setModel}
  placeholder="Ask anything…"
/>

3. Wire streaming to your backend

Herald doesn't own your backend. useStream turns any SSE/fetch stream into live parts[]: you hand it a request(signal), it owns the parsing, state, and abort.

import { useStream } from "@/hooks/use-stream"

const stream = useStream()

async function send(text: string) {
  const res = await stream.start((signal) =>
    fetch("/api/chat", {
      method: "POST",
      body: JSON.stringify({ text }),
      signal,
    })
  )
  // res.acc → the accumulated parts[]; stream.parts stays live while streaming
}

The parser is swappable — the default speaks OpenAI-compatible SSE, but you can pass your own for any wire format.

4. Add surfaces

From there you compose the rest of the cockpit — a ⌘K command bar, a tool-call feed, fleet and gallery views. Because they share the same typed contracts, they snap together instead of fighting each other. More block surfaces are on the way — see the greyed items in the sidebar.

5. Make it yours

One brand hue re-themes the entire system — see Installation for the token layer. Copy the source of anything and bend it; that's the whole point.

Explore

Every component in the sidebar has a live preview and copy-paste source. The Chat and App Shell blocks are the fastest way to see it all come together.