From ai-elements-chatbot
Adds shadcn/ui AI chat UI components for Next.js App Router with Vercel AI SDK v5, supporting streaming responses, tool calls, reasoning visualization, and markdown rendering.
npx claudepluginhub secondsky/claude-skills --plugin ai-elements-chatbotThis skill uses the workspace's default tool permissions.
**Status**: Production Ready ✅ | **Last Verified**: 2025-11-18
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Status: Production Ready ✅ | Last Verified: 2025-11-18
Production-ready chat UI components for AI applications:
pnpm dlx ai-elements@latest init
pnpm dlx ai-elements@latest add message conversation response prompt-input
'use client';
import { useChat } from 'ai/react';
import { Conversation } from '@/components/ui/ai/conversation';
import { Message } from '@/components/ui/ai/message';
import { Response } from '@/components/ui/ai/response';
import { PromptInput } from '@/components/ui/ai/prompt-input';
export default function ChatPage() {
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: '/api/chat'
});
return (
<div className="flex h-screen flex-col">
<Conversation>
{messages.map((msg) => (
<Message key={msg.id} role={msg.role}>
<Response markdown={msg.content} />
</Message>
))}
</Conversation>
<PromptInput
value={input}
onChange={handleInputChange}
onSubmit={handleSubmit}
/>
</div>
);
}
Load references/setup-guide.md for complete setup.
import { Conversation } from '@/components/ui/ai/conversation';
import { Message } from '@/components/ui/ai/message';
<Conversation>
{messages.map((msg) => (
<Message key={msg.id} role={msg.role}>
{msg.content}
</Message>
))}
</Conversation>
import { Response } from '@/components/ui/ai/response';
<Response markdown={content} />
import { PromptInput } from '@/components/ui/ai/prompt-input';
<PromptInput
value={input}
onChange={handleInputChange}
onSubmit={handleSubmit}
/>
import { CodeBlock } from '@/components/ui/ai/code-block';
<CodeBlock code={code} language="typescript" />
import { Reasoning } from '@/components/ui/ai/reasoning';
<Reasoning content={thinking} />
import { Tool } from '@/components/ui/ai/tool';
<Tool name="search" args={{ query: "..." }} result={result} />
pnpm dlx ai-elements@latest)Core:
Content:
Actions:
Advanced:
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<>
<Conversation>
{messages.map(m => (
<Message key={m.id} role={m.role}>
<Response markdown={m.content} />
</Message>
))}
</Conversation>
<PromptInput value={input} onChange={handleInputChange} onSubmit={handleSubmit} />
</>
);
{messages.map(m => (
<Message key={m.id} role={m.role}>
{m.toolInvocations?.map(tool => (
<Tool key={tool.toolCallId} name={tool.toolName} args={tool.args} result={tool.result} />
))}
<Response markdown={m.content} />
</Message>
))}
<Message role="assistant">
{reasoning && <Reasoning content={reasoning} />}
<Response markdown={content} />
</Message>
<Response markdown={content}>
{(node) => node.type === 'code' ? (
<CodeBlock code={node.value} language={node.lang} />
) : null}
</Response>
<Message role="assistant">
<Response markdown={content} />
<Sources sources={sources} />
</Message>
// app/api/chat/route.ts
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4'),
messages
});
return result.toDataStreamResponse();
}
const result = streamText({
model: openai('gpt-4'),
messages,
tools: {
search: {
description: 'Search the web',
parameters: z.object({ query: z.string() }),
execute: async ({ query }) => {
return await search(query);
}
}
}
});
Use when:
Don't use when:
References (references/):
component-catalog.md - All 8 AI Elements components with examplesexample-reference.md - Complete integration examples and patternssetup-guide.md - Step-by-step setup with Next.js 15 and shadcn/uiTemplates (templates/):
Questions? Issues?
references/setup-guide.md for complete setup