Getting started
Usage
After installing, import components and render them. Stream chat with the AI SDK or the built-in hooks, theme any subtree with one attribute, and reach for blocks when you want a whole surface.
Render
Components
tsx
import { ChatBubble, ToolCard } from "@skeehn/react";
export function Demo() {
return (
<>
<ChatBubble role="user">Summarize this thread.</ChatBubble>
<ChatBubble role="assistant">Three decisions, two open questions.</ChatBubble>
<ToolCard name="search" status="success">3 results</ToolCard>
</>
);
}Stream
With the AI SDK (recommended)
skeehn renders @ai-sdk/react messages directly — text, reasoning, tool calls and sources are mapped to the right components.
tsx
"use client";
import { useChat } from "@ai-sdk/react";
import { Conversation } from "@skeehn/react/ai";
export function Chat() {
const { messages } = useChat(); // AI SDK v5
return <Conversation messages={messages} />; // parts → skeehn, mapped for you
}Prefer zero dependencies? The built-in hook works too:
tsx
"use client";
import { useChat } from "@skeehn/react/hooks"; // zero-dep, no AI SDK required
import { ChatBubble } from "@skeehn/react";
export function Chat() {
const { messages } = useChat({ api: "/api/chat" });
return messages.map((m) => <ChatBubble key={m.id} role={m.role}>{m.content}</ChatBubble>);
}Compose
Blocks — whole interfaces
Drop-in surfaces from @skeehn/react/blocks: ChatConsole, AgentConsole, VoiceConsole, HeroSection.
tsx
import { ChatConsole } from "@skeehn/react/blocks";
<ChatConsole
messages={messages}
busy={status === "streaming"}
onSend={(text) => sendMessage({ text })}
/>;Theme
Re-skin any subtree
Every component reads one token contract. Change data-theme on any ancestor and the whole subtree re-skins — no rewrites.
tsx
<div data-theme="terminal">{/* this subtree is green-phosphor CRT */}</div>Next: Browse components · Blocks · Use anywhere