Join our Discord Community

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:

Loading component...

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.

PropTypeDefaultDescription
childrenstring | ReactNode-Required - Markdown content to render
optionsReactMarkdown["options"]-React Markdown configuration options
allowedImagePrefixesstring[]["*"]Allowed image URL prefixes for security
allowedLinkPrefixesstring[]["*"]Allowed link URL prefixes for security
defaultOriginstring-Default origin for relative URLs
parseIncompleteMarkdownbooleantrueEnable intelligent streaming parsing
classNamestring-Additional CSS classes
...propsHTMLAttributes<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