Building AI-Powered React Components with Vercel AI SDK
ReactComplete guide to integrating AI capabilities into React applications using Vercel's AI SDK. Build chatbots, content generators, and smart UI components with streaming responses

The Vercel AI SDK makes it incredibly easy to add AI capabilities to React applications. In this tutorial, we'll build several AI-powered components from scratch, including a streaming chatbot and intelligent content generator.
Getting Started
First, install the necessary packages:
npm install ai @ai-sdk/openai @ai-sdk/anthropic
npm install @types/react @types/node # if using TypeScript
Set up your environment variables:
# .env.local
OPENAI_API_KEY=your_openai_key
ANTHROPIC_API_KEY=your_anthropic_key
Basic Chat Component
Let's start with a simple chat interface that streams responses:
// components/ChatBot.jsx
import { useChat } from 'ai/react';
import { useState } from 'react';
export default function ChatBot() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: '/api/chat',
});
return (
<div className="chat-container">
<div className="messages">
{messages.map((message) => (
<div key={message.id} className={`message ${message.role}`}>
<strong>{message.role === 'user' ? 'You' : 'AI'}:</strong>
<p>{message.content}</p>
</div>
))}
{isLoading && <div className="loading">AI is thinking...</div>}
</div>
<form onSubmit={handleSubmit} className="input-form">
<input
value={input}
onChange={handleInputChange}
placeholder="Ask me anything..."
disabled={isLoading}
/>
<button type="submit" disabled={isLoading}>
Send
</button>
</form>
</div>
);
}
API Route Setup
// pages/api/chat.js (or app/api/chat/route.js for App Router)
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export async function POST(req) {
const { messages } = await req.json();
const result = await streamText({
model: openai('gpt-4-turbo'),
messages,
system: 'You are a helpful assistant that provides concise, accurate answers.',
});
return result.toAIStreamResponse();
}
useChat Hook Features:
Built-in State Management
- Automatic message history
- Loading states
- Error handling
- Input management
Streaming Support
- Real-time response streaming
- Partial message updates
- Automatic UI updates
Customization Options
- Custom API endpoints
- Message preprocessing
- Response formatting
- Error callbacks
Advanced Content Generator
Let's build a more sophisticated component that generates blog content:
// components/ContentGenerator.jsx
import { useCompletion } from 'ai/react';
import { useState } from 'react';
export default function ContentGenerator() {
const [topic, setTopic] = useState('');
const [contentType, setContentType] = useState('blog-post');
const {
completion,
input,
handleInputChange,
handleSubmit,
isLoading,
error,
} = useCompletion({
api: '/api/generate',
body: {
contentType,
topic,
},
});
const handleGenerate = (e) => {
e.preventDefault();
handleSubmit(e, {
body: {
prompt: input,
contentType,
topic,
},
});
};
return (
<div className="content-generator">
<div className="controls">
<input
type="text"
placeholder="Enter topic..."
value={topic}
onChange={(e) => setTopic(e.target.value)}
/>
<select
value={contentType}
onChange={(e) => setContentType(e.target.value)}
>
<option value="blog-post">Blog Post</option>
<option value="social-media">Social Media</option>
<option value="email">Email</option>
<option value="product-description">Product Description</option>
</select>
<form onSubmit={handleGenerate}>
<textarea
value={input}
onChange={handleInputChange}
placeholder="Additional instructions..."
rows={3}
/>
<button type="submit" disabled={isLoading || !topic}>
{isLoading ? 'Generating...' : 'Generate Content'}
</button>
</form>
</div>
{error && (
<div className="error">
Error: {error.message}
</div>
)}
{completion && (
<div className="generated-content">
<h3>Generated Content:</h3>
<div className="content-preview">
{completion.split('\n').map((paragraph, index) => (
<p key={index}>{paragraph}</p>
))}
</div>
<button onClick={() => navigator.clipboard.writeText(completion)}>
Copy to Clipboard
</button>
</div>
)}
</div>
);
}
API Route for Content Generation
// pages/api/generate.js
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
const contentPrompts = {
'blog-post': 'Write a comprehensive blog post about',
'social-media': 'Create engaging social media content about',
'email': 'Write a professional email about',
'product-description': 'Create a compelling product description for',
};
export async function POST(req) {
const { prompt, contentType, topic } = await req.json();
const systemPrompt = `${contentPrompts[contentType]} ${topic}. ${prompt || ''}
Guidelines:
- Keep the tone professional but engaging
- Include relevant keywords naturally
- Structure content with clear headings
- Make it actionable and valuable`;
const result = await streamText({
model: openai('gpt-4-turbo'),
prompt: systemPrompt,
temperature: 0.7,
maxTokens: 1000,
});
return result.toAIStreamResponse();
}
Comments