Introducing EasyRAG React Components
Production-ready React components for file upload, search, and chat. Add RAG to your app in minutes.
Introducing EasyRAG React Components
Building RAG interfaces shouldn't require days of development. Today, we're launching production-ready React components that let you add document upload, semantic search, and AI chat to your application in minutes.
The Problem
Every developer building a RAG application faces the same challenges:
- File Upload UI - Drag-and-drop, progress bars, validation
- Search Interface - Query input, results display, filtering
- Chat Experience - Message history, streaming, auto-scroll
- File Management - Listing, previewing, deleting files
You can build these from scratch, but that's weeks of work before you even start on your actual product features.
Our Solution
Four production-ready React components:
tsximport { FileUpload, SearchBox, ChatBox, FileViewer } from '@easyrag/react-components';
Drop them into your React app. They just work.
Quick Demo
Here's a complete RAG application in 30 lines:
tsximport { useState, useEffect } from 'react'; import { FileUpload, SearchBox, ChatBox } from '@easyrag/react-components'; function MyRAGApp() { const [token, setToken] = useState(''); // Get token from your backend useEffect(() => { fetch('/api/tokens/create', { method: 'POST' }) .then(r => r.json()) .then(data => setToken(data.token)); }, []); if (!token) return <div>Loading...</div>; return ( <div className="max-w-4xl mx-auto p-6 space-y-8"> <h1>My Documents</h1> {/* Upload files */} <FileUpload token={token} datasetId="my-dataset" /> {/* Search documents */} <SearchBox token={token} datasetId="my-dataset" /> {/* Chat with documents */} <ChatBox token={token} datasetId="my-dataset" stream={true} /> </div> ); }
That's it. Upload, search, and chat - all working, all secure, all customizable.
What's Included
FileUpload Component
Drag-and-drop file upload with everything you need:
tsx<FileUpload token={token} datasetId="documents" maxFiles={10} maxFileSize={10 * 1024 * 1024} accept={{ 'application/pdf': ['.pdf'] }} metadataBuilder={(file) => ({ userId: currentUser.id, department: currentUser.department, uploadedAt: new Date().toISOString() })} onUploadComplete={(result) => { console.log(`Uploaded ${result.files.length} files`); }} />
Features:
- ✅ Drag & drop interface
- ✅ Multi-file upload
- ✅ Progress indicators
- ✅ File type restrictions
- ✅ Size limits
- ✅ Metadata attachment
- ✅ Custom chunking options
- ✅ Error handling
SearchBox Component
Semantic search with beautiful results:
tsx<SearchBox token={token} datasetId="knowledge-base" filters={[ { key: 'department', match: { value: 'engineering' } } ]} showScore={true} showMetadata={false} onResults={(results) => { console.log(`Found ${results.length} results`); }} />
Features:
- ✅ Search input & button
- ✅ Real-time results display
- ✅ Relevance score showing
- ✅ Metadata filtering
- ✅ Custom result rendering
- ✅ Empty state handling
- ✅ Loading states
ChatBox Component
AI chat with streaming responses:
tsx<ChatBox token={token} datasetId="support-docs" stream={true} maxHeight="600px" initialMessages={[ { id: 1, role: 'assistant', content: 'Hi! How can I help you today?' } ]} filters={[ { key: 'category', match: { value: 'billing' } } ]} />
Features:
- ✅ Streaming responses (optional)
- ✅ Message history
- ✅ Auto-scroll to latest
- ✅ User/Assistant styling
- ✅ Initial messages support
- ✅ Metadata filtering
- ✅ Error recovery
FileViewer Component
Browse and manage uploaded files:
tsx<FileViewer token={token} datasetId="my-dataset" onFileSelect={(file) => { console.log('Selected:', file.originalName); }} onFileDelete={(fileId) => { console.log('Deleted:', fileId); refetchFiles(); }} />
Features:
- ✅ File list with metadata
- ✅ File selection & preview
- ✅ Permanent URLs
- ✅ Delete functionality
- ✅ Transcription display (for media)
- ✅ Custom filter support
Three Ways to Use
1. Zero Configuration
Just pass token and datasetId:
tsx<FileUpload token={token} datasetId="dataset" />
Uses sensible defaults. Perfect for MVPs.
2. Light Customization
Adjust behavior with props:
tsx<SearchBox token={token} datasetId="dataset" theme="minimal" showScore={true} maxResults={5} filters={[ { key: 'status', match: { value: 'published' } } ]} />
3. Full Customization
Complete control over styling:
tsx<ChatBox token={token} datasetId="dataset" theme="custom" customStyles={{ container: 'my-chat-container', messageUser: 'bg-blue-600 text-white rounded-lg px-4 py-2', messageAssistant: 'bg-gray-100 rounded-lg px-4 py-2', input: 'border-2 border-gray-300 rounded-lg px-4 py-2', button: 'bg-blue-600 text-white rounded-lg px-6 py-2' }} labels={{ placeholder: 'Ask me anything...', buttonSend: 'Submit' }} />
Built for Real Apps
Secure by Default
Components use frontend token authentication. Your API keys stay on the backend where they belong.
typescript// Backend generates short-lived token app.post('/api/tokens/create', authenticate, async (req, res) => { const token = signFrontendToken({ customerId: req.user.id, datasetId: req.body.datasetId, ttlSeconds: 3600 // 1 hour }); res.json({ token }); }); // Frontend uses token securely <FileUpload token={token} datasetId="dataset" />
No API keys in your bundle. No security risks.
Multi-Tenant Ready
Filter by user, department, or any metadata:
tsx// Upload with tenant metadata <FileUpload token={token} datasetId="shared-docs" metadataBuilder={(file) => ({ userId: currentUser.id, department: currentUser.department, confidential: false })} /> // Search only user's documents <SearchBox token={token} datasetId="shared-docs" filters={[ { key: 'userId', match: { value: currentUser.id } } ]} /> // Chat with department docs <ChatBox token={token} datasetId="shared-docs" filters={[ { key: 'department', match: { value: currentUser.department } } ]} />
Perfect for SaaS apps with multiple tenants.
TypeScript Support
Full type definitions included:
typescriptimport type { FileUploadProps, SearchBoxProps, SearchResult, ChatBoxProps, Message, FileViewerProps } from '@easyrag/react-components'; const handleResults = (results: SearchResult[]) => { results.forEach(result => { console.log(result.score); // number console.log(result.pageContent); // string console.log(result.metadata); // Record<string, any> }); };
Autocomplete and type safety everywhere.
Production Ready
- ✅ Error boundaries
- ✅ Loading states
- ✅ Empty states
- ✅ Responsive design
- ✅ Accessibility (ARIA labels)
- ✅ Browser tested
Real-World Examples
Customer Support Portal
tsxfunction SupportPortal() { return ( <div className="grid grid-cols-2 gap-8"> {/* Left: Search knowledge base */} <SearchBox token={token} datasetId="support-kb" filters={[ { key: 'category', match: { value: 'billing' } } ]} renderResult={(result) => ( <article className="p-4 border rounded"> <h3 className="font-bold">{result.metadata.title}</h3> <p className="text-sm text-gray-600">{result.pageContent}</p> <span className="text-xs text-gray-500"> Relevance: {(result.score * 100).toFixed(0)}% </span> </article> )} /> {/* Right: AI assistant */} <ChatBox token={token} datasetId="support-kb" stream={true} initialMessages={[ { id: 1, role: 'assistant', content: 'Hi! I can help with billing questions.' } ]} /> </div> ); }
Document Management System
tsxfunction DocumentManager() { const [selectedFile, setSelectedFile] = useState(null); return ( <div className="space-y-6"> {/* Upload new documents */} <FileUpload token={token} datasetId="company-docs" accept={{ 'application/pdf': ['.pdf'], 'application/msword': ['.doc', '.docx'] }} metadataBuilder={(file) => ({ uploadedBy: currentUser.email, department: currentUser.department, uploadDate: new Date().toISOString() })} /> {/* Browse existing documents */} <FileViewer token={token} datasetId="company-docs" onFileSelect={setSelectedFile} /> {/* Search all documents */} {selectedFile && ( <SearchBox token={token} datasetId="company-docs" filters={[ { key: 'fileId', match: { value: selectedFile.fileId } } ]} /> )} </div> ); }
Research Assistant
tsxfunction ResearchAssistant() { return ( <div className="max-w-6xl mx-auto"> <div className="grid grid-cols-3 gap-6"> {/* Upload papers */} <div className="col-span-1"> <h2>Upload Papers</h2> <FileUpload token={token} datasetId="research-papers" accept={{ 'application/pdf': ['.pdf'] }} metadataBuilder={(file) => ({ author: extractAuthor(file.name), year: extractYear(file.name), topic: currentTopic })} /> </div> {/* Chat with papers */} <div className="col-span-2"> <h2>Ask Questions</h2> <ChatBox token={token} datasetId="research-papers" stream={true} maxHeight="500px" filters={[ { key: 'topic', match: { value: currentTopic } } ]} /> </div> </div> </div> ); }
Customization Options
Three Built-In Themes
Default Theme - Clean, modern EasyRAG styling:
tsx<SearchBox token={token} datasetId="dataset" theme="default" />
Minimal Theme - Lightweight, easy to integrate:
tsx<SearchBox token={token} datasetId="dataset" theme="minimal" />
Custom Theme - Your own styles:
tsx<SearchBox token={token} datasetId="dataset" theme="custom" customStyles={{ container: 'my-search', input: 'border-2 border-blue-500 rounded p-2', button: 'bg-blue-600 text-white px-4 py-2 rounded', resultCard: 'border p-4 rounded shadow-sm' }} />
Custom Labels
Change any text:
tsx<FileUpload token={token} datasetId="dataset" labels={{ dropzone: 'Drop your files here', dropzoneActive: 'Release to upload', uploading: 'Processing...', }} />
Branding
All components include an optional "Powered by EasyRAG" watermark:
tsx// Show (default) <ChatBox token={token} datasetId="dataset" showPoweredBy={true} /> // Hide <ChatBox token={token} datasetId="dataset" showPoweredBy={false} /> // Custom URL <ChatBox token={token} datasetId="dataset" poweredByUrl="https://yourcompany.com" />
Installation
bashnpm install @easyrag/react-components
Framework Support
Works with:
- ✅ Next.js (App Router & Pages Router)
- ✅ Vite
- ✅ Remix
- ✅ Any React 18+ app
Get Started
1. Install
bashnpm install @easyrag/react-components
2. Get API Key
Sign up at easyrag.com and create an API key.
3. Build
tsximport { FileUpload, SearchBox, ChatBox } from '@easyrag/react-components'; function App() { return ( <div> <FileUpload token={token} datasetId="dataset" /> <SearchBox token={token} datasetId="dataset" /> <ChatBox token={token} datasetId="dataset" /> </div> ); }
Resources
Coming Soon
We're working on:
- 📊 Analytics Component - Usage charts and insights
- 🎨 More Themes - Dark mode, accessibility themes
- 🔌 More Frameworks - Vue, Svelte, Angular components
- 📱 Mobile Components - React Native support
- 🎯 Advanced Components - Document comparison, summarization views
Want something specific? Let us know!
Why We Built This
We've built RAG applications for years. Every time, we rebuilt the same interfaces: upload, search, chat.
We realized 90% of RAG UIs are identical. Why rebuild them?
These components are the UI layer we wish existed when we started.
Try It Now
Ready to add RAG to your app?
- Sign up for free (20 free credits)
- Install:
npm install @easyrag/react-components - Follow our Quick Start Guide
Build your RAG app today. No credit card required.
