Guide
Installation
Herald is distributed the shadcn way: you install a component's source straight into your project and own it — no package to wrap, no black box to fight.
Prerequisites
- A React app: Next.js, Vite, Remix — anything that renders React 19.
- Tailwind CSS v4: Herald's tokens use the CSS-first @theme layer.
- shadcn/ui, initialized: Run npx shadcn@latest init once. A standard init is all you need — no special style or preset; Herald ships its own primitives, so pick any base color.
- Base UI: Components are built on @base-ui/react — you don't install it yourself; each item declares it as a dependency, so shadcn add pulls it in automatically.
- tw-animate-css: Overlay enter/exit animations use its utilities — add @import "tw-animate-css"; next to tailwindcss in your globals.css (the registry installs the package).
Connect the registry
Register the Herald namespace once in your components.json. After this, @herald-ui/* resolves for every command on this site.
{
"registries": {
"@herald-ui": "https://herald-ui.vercel.app/r/{name}.json"
}
}That's the only setup — one paste, once per project. It lets components pull their own Herald dependencies (a chat panel quietly brings its thread, composer, and model picker) all from the same place.
Add a component
Pull any component in by name. The command is listed on every component's page.
Swap button for any item — thread, chat-panel, kanban-board. Components land in components/ui/, blocks in blocks/, hooks in hooks/ — import them from @/ (e.g. @/blocks/chat-panel), and any npm dependencies install automatically.
A block re-declares shared primitives (button, badge, its own utils), so shadcn may prompt to overwrite files you already have. Herald's versions are the intended ones — keep them, or pass --overwrite to accept them without prompting (needed for scripted or agent-run installs, since --yes doesn't answer overwrite prompts).
Prefer to copy?
Every component's Details drawer has the full source. Paste it into components/ui/ and you own it outright — no registry required. That's the shadcn model, and it works today.
Wire up the tokens
Herald is themed with OKLCH tokens and a single brand hue. Pull the token layer in:
This drops a standalone app/tokens.css — a complete replacement for the token block shadcn init wrote. Two steps to wire it in your globals.css:
@import "tailwindcss";
@import "tw-animate-css";
@import "./tokens.css"; /* Herald's tokens */
/* …and DELETE the :root { }, .dark { }, and @theme { } color
block that shadcn init generated above — see the note below. */Don't skip the delete step
shadcn init writes its own :root/.dark/@theme color block that doesn't define --brand, --success, or the ease-* motion curves. If you leave it in, it wins over Herald's — and components render with no brand color and dead animations, with no error. Herald's tokens.css is the full set; it must be the only one.
Using any chat surface (ChatPanel, Thread, Markdown)? Add the chat stylesheet the same way and @import "./chat.css" below the tokens:
With that in place the whole system keys off three variables — change them and every component follows, ring and charts included. The paintbrush in the corner of any preview on this site edits exactly these, live.
:root {
--brand-hue: 27; /* your accent, on the OKLCH hue wheel */
--brand-chroma: 0.24; /* saturation */
--radius: 0.625rem; /* parametrizes every radius token */
}Use it
import { Button } from "@/components/ui/button"
export function Example() {
return <Button variant="brand">Get started</Button>
}Next
Compose the pieces into a working cockpit — Getting Started.