React AI Response
Streaming-optimized markdown renderer with syntax highlighting. Build rich AI content with React, Next.js, and TypeScript, featuring auto-completion of incomplete formatting and code blocks for shadcn/ui applications.
Trying to implement AI Elements?
Join our Discord community for help from other developers.
Streaming markdown without smart parsing shows users broken **bold
and incomplete [links
in React applications. This free open source component auto-completes formatting as content arrives and hides broken elements until ready in Next.js projects.
Intelligent streaming markdown
Auto-completing formatting with syntax highlighting:
The React component automatically completes incomplete bold, italic, and code formatting during streaming, hides broken links until complete, and renders syntax-highlighted code blocks with copy buttons. Built with TypeScript for type safety and designed for seamless integration in your JavaScript projects.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/ai.json
npx shadcn@latest add https://www.shadcn.io/registry/ai.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/ai.json
bunx shadcn@latest add https://www.shadcn.io/registry/ai.json
Usage
import { Response } from "@/components/ai/response";
<Response>**Hi there.** I am an AI model designed to help you.</Response>;
For code blocks, nest markdown inside the Response component:
<Response>
{`Here's some code:
\`\`\`javascript
const greeting = "Hello, world!";
console.log(greeting);
\`\`\`
`}
</Response>
Why streaming markdown is hard
AI responses stream character by character in React applications. Regular markdown parsers show **incomplete bold
and [broken links
while text arrives in Next.js projects. This looks buggy and unprofessional in JavaScript implementations.
The TypeScript component fixes this by auto-completing formatting tokens and hiding incomplete links until ready. Users see clean text throughout the entire stream in React applications.
Usage with AI SDK
Render streaming AI responses with intelligent formatting in React applications:
"use client";
import {
Conversation,
ConversationContent,
} from "@/components/ai/conversation";
import { Message, MessageContent } from "@/components/ai/message";
import {
PromptInput,
PromptInputTextarea,
PromptInputSubmit,
} from "@/components/ai/prompt-input";
import { Response } from "@/components/ai/response";
import { useChat } from "@ai-sdk/react";
import { useState } from "react";
export default function ResponseDemo() {
const [input, setInput] = useState("");
const { messages, append, status } = useChat();
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (input.trim()) {
append({ role: "user", content: input });
setInput("");
}
};
return (
<div className="flex flex-col h-full max-w-4xl mx-auto">
<Conversation>
<ConversationContent>
{messages.map((message) => (
<Message from={message.role} key={message.id}>
<MessageContent>
{message.parts?.map((part, i) => {
switch (part.type) {
case "text":
return (
<Response key={`${message.id}-${i}`}>
{part.text}
</Response>
);
default:
return null;
}
})}
</MessageContent>
</Message>
))}
</ConversationContent>
</Conversation>
<PromptInput onSubmit={handleSubmit}>
<PromptInputTextarea
value={input}
onChange={(e) => setInput(e.currentTarget.value)}
placeholder="Ask for markdown content..."
/>
<PromptInputSubmit disabled={!input.trim()} status={status} />
</PromptInput>
</div>
);
}
Backend route for markdown-rich responses:
// app/api/chat/route.ts
import { streamText, convertToModelMessages } from "ai";
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: "openai/gpt-4o",
messages: convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse();
}
Features
- Streaming-optimized parsing - Auto-completes incomplete formatting during streaming in React applications
- Rich markdown support - Paragraphs, headers, lists, tables, blockquotes, and more in TypeScript components
- Syntax-highlighted code blocks - Multiple programming languages with copy buttons for JavaScript frameworks
- Math equation support - LaTeX rendering via rehype-katex in Next.js projects
- GFM features - Tables, task lists, strikethrough via remark-gfm
- Link and image security - Configurable allowed prefixes for safety
- Intelligent hiding - Incomplete links and images hidden until complete
- Responsive design - Adapts to different screen sizes while maintaining readability
- Theme-aware styling - Works seamlessly in light and dark modes
- Accessibility focused - Proper semantic HTML and screen reader support
- Perfect for AI assistants and conversational AI interfaces - Built specifically for streaming AI content
- Free open source component built for Next.js with shadcn/ui design system and AI Elements
- Optimized for Vercel AI SDK streaming and AI chat applications
API Reference
Response
Markdown renderer with intelligent streaming support.
Prop | Type | Default | Description |
---|---|---|---|
children | string | ReactNode | - | Required - Markdown content to render |
options | ReactMarkdown["options"] | - | React Markdown configuration options |
allowedImagePrefixes | string[] | ["*"] | Allowed image URL prefixes for security |
allowedLinkPrefixes | string[] | ["*"] | Allowed link URL prefixes for security |
defaultOrigin | string | - | Default origin for relative URLs |
parseIncompleteMarkdown | boolean | true | Enable intelligent streaming parsing |
className | string | - | Additional CSS classes |
...props | HTMLAttributes<HTMLDivElement> | - | Standard div attributes |
Streaming optimizations
The Response component includes several intelligent parsing features:
Auto-completion of incomplete formatting
- Bold:
**incomplete
→**incomplete**
(auto-closed) - Italic:
*incomplete
→*incomplete*
(auto-closed) - Strikethrough:
~~incomplete
→~~incomplete~~
(auto-closed) - Inline code:
`incomplete
→`incomplete`
(auto-closed)
Hiding incomplete elements
- Links:
[incomplete text
(hidden until]
appears) - Images:
![incomplete alt
(hidden until]
appears) - Code blocks: Protects triple backticks from inline code completion
Smart parsing behavior
- Only applies during streaming when
parseIncompleteMarkdown={true}
in React applications - Preserves code block boundaries to prevent interference in TypeScript components
- Counts formatting tokens to determine completion needs in JavaScript implementations
- Works with both single and double character formatters in Next.js projects
Security considerations
Always validate allowed prefixes. The default ["*"]
allows all URLs in React applications. In production, restrict to trusted domains in Next.js projects:
<Response
allowedImagePrefixes={["https://yourdomain.com", "https://cdn.example.com"]}
allowedLinkPrefixes={["https://", "mailto:"]}
>
{content}
</Response>
Content sanitization is built-in. The React component uses harden-react-markdown
for XSS protection in TypeScript implementations.
Integration with other components
Response works seamlessly with Message for chat interfaces in React applications. Use within Conversation for scrolling markdown content in Next.js projects. Combine with CodeBlock for enhanced code display. This free open source component integrates seamlessly with modern JavaScript frameworks.
Questions developers actually ask
React AI Reasoning
Collapsible AI reasoning display with auto-streaming behavior. Build transparent AI interfaces with React, Next.js, and TypeScript, featuring automatic open/close and duration tracking for shadcn/ui applications.
React AI Sources
Collapsible citation display for AI-generated content. Build transparent AI interfaces with React, Next.js, and TypeScript, featuring expandable source links and customizable citation counts for shadcn/ui applications.