Installation
Everything here assumes a React project with Tailwind v4 and shadcn/ui already set up. Components are copied into your repo, so there is no runtime package to keep in sync.
Prerequisites
- A
components.jsonat the project root — runnpx shadcn@latest initif you do not have one. - Tailwind CSS v4 with the shadcn CSS variables defined (
initwrites them for you). - React 19, and Node 20.9 or newer for the CLI.
The components import cn() from @/lib/utils and resolve shadcn primitives through the aliases in components.json. Missing primitives (dropdown menu, context menu, collapsible) are pulled in automatically.
Install the kit
The chat block installs a working chat surface plus every atom it composes.
npx shadcn@latest add miskibin/chat-components/chatInstall single atoms
Nothing here needs the block. Add only what you use — each item pulls its own dependencies.
npx shadcn@latest add miskibin/chat-components/chat-input
npx shadcn@latest add miskibin/chat-components/prompt-suggestions
npx shadcn@latest add miskibin/chat-components/todo-list
npx shadcn@latest add miskibin/chat-components/chat-navbar
npx shadcn@latest add miskibin/chat-components/resizable
npx shadcn@latest add miskibin/chat-components/message
npx shadcn@latest add miskibin/chat-components/message-list
npx shadcn@latest add miskibin/chat-components/message-parts
npx shadcn@latest add miskibin/chat-components/ask-question
npx shadcn@latest add miskibin/chat-components/plan-card
npx shadcn@latest add miskibin/chat-components/message-markdown
npx shadcn@latest add miskibin/chat-components/render-error-boundary
npx shadcn@latest add miskibin/chat-components/change-summary
npx shadcn@latest add miskibin/chat-components/file-preview
npx shadcn@latest add miskibin/chat-components/diff-view
npx shadcn@latest add miskibin/chat-components/file-tree
npx shadcn@latest add miskibin/chat-components/file-icon
npx shadcn@latest add miskibin/chat-components/generation-status
npx shadcn@latest add miskibin/chat-components/folder-picker
npx shadcn@latest add miskibin/chat-components/model-picker
npx shadcn@latest add miskibin/chat-components/mode-picker
npx shadcn@latest add miskibin/chat-components/context-meter
npx shadcn@latest add miskibin/chat-components/theme-toggle
npx shadcn@latest add miskibin/chat-components/chat-sidebar
npx shadcn@latest add miskibin/chat-components/sidebar-item
npx shadcn@latest add miskibin/chat-components/sidebar-dnd
npx shadcn@latest add miskibin/chat-components/sidebar-drop-zones
npx shadcn@latest add miskibin/chat-components/sidebar-resize-rail
npx shadcn@latest add miskibin/chat-components/use-click-outsideMarkdown rendering
Message Markdown renders answers with Streamdown (GFM, Shiki, Mermaid, KaTeX). Those packages ship Tailwind utility classes inside their own dist files, so two build settings are required — without them the markdown renders unstyled.
1. Tailwind sources
Add these next to your @import "tailwindcss" so the utilities are generated.
@import "tailwindcss";
@import "streamdown/styles.css";
@source "../node_modules/streamdown/dist/*.js";
@source "../node_modules/@streamdown/code/dist/*.js";
@source "../node_modules/@streamdown/mermaid/dist/*.js";
@source "../node_modules/@streamdown/math/dist/*.js";2. Transpile the packages
On Next.js, add them to the config.
import type { NextConfig } from "next"
const nextConfig: NextConfig = {
transpilePackages: [
"streamdown",
"@streamdown/code",
"@streamdown/mermaid",
"@streamdown/math",
"mermaid",
],
}
export default nextConfigProviders
ThemeToggle and the markdown renderer read the resolved theme from next-themes, so mount the provider once at the root. The examples in these docs also use sonner for toasts — optional, but the Toaster has to be mounted if you copy them verbatim.
npm install next-themes sonnerimport { ThemeProvider } from "next-themes"
import { Toaster } from "sonner"
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" suppressHydrationWarning>
<body suppressHydrationWarning>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
<Toaster position="top-right" richColors />
</body>
</html>
)
}Layout
The chat surface fills its parent and manages its own inner scrolling, so give the parent an explicit height and let the message list own the overflow.
<div className="flex h-svh min-h-0 flex-col overflow-hidden">
<ChatNavbar title={title} />
<MessageList className="flex-1" messages={messages} />
<ChatInput onSend={send} />
</div>