🌐 AI Web Search Made Simple
Right now, your AI can chat, generate images, transcribe audio, analyze files, synthesize speech, understand vision, have voice conversations, and call functions. But what if your AI could search the internet for current information?
Web search opens up unlimited current knowledge. Instead of being limited to training data, your AI can search the web in real-time to find recent news, current prices, latest information, and answer questions about events that happened after its training cutoff.
You’re about to learn exactly how to give your AI real-time internet access through web search.
🧠 Step 1: Understanding AI Web Search
Section titled “🧠 Step 1: Understanding AI Web Search”Before we write any code, let’s understand what AI web search actually means and why it transforms your AI from having static knowledge to having access to all current information.
What AI Web Search Actually Means
Section titled “What AI Web Search Actually Means”AI web search is like giving your AI unlimited access to current information. Instead of only knowing what it learned during training, your AI can search the internet to find the most recent information about any topic.
Real-world analogy: It’s like hiring a research assistant who can instantly search the entire internet to find current information. Instead of saying “I don’t know about recent events,” they can search and give you up-to-date answers about anything happening right now.
Why Web Search vs. Static Knowledge
Section titled “Why Web Search vs. Static Knowledge”Your existing AI has limitations with current information:
📚 Static Knowledge - AI knows about topics up to its training cutoff date 🌐 Web Search - AI can find information about current events and recent developments
📚 Static Knowledge - AI might give outdated prices or information
🌐 Web Search - AI can find current prices, news, and real-time data
📚 Static Knowledge - AI can’t answer questions about recent events 🌐 Web Search - AI can research and provide information about anything recent
Real-World Use Cases
Section titled “Real-World Use Cases”Think about all the current information your AI could access with web search:
- Current events - Latest news and breaking stories
- Real-time prices - Current stock prices, cryptocurrency values, product costs
- Recent research - Latest scientific studies and discoveries
- Weather updates - Current weather conditions and forecasts
- Sports scores - Live game results and standings
- Product information - Latest product reviews and specifications
Without web search, your AI can only:
- Rely on training data (potentially outdated)
- Make educated guesses (potentially inaccurate)
- Say “I don’t know about recent events” (not helpful)
With web search, your AI can:
- Find current information about any topic
- Provide accurate, up-to-date answers with sources
- Research recent developments and breaking news
Web Search Architecture
Section titled “Web Search Architecture”Your web search system will work in three steps:
🔍 Step 1: Search Query - AI decides what to search for based on user question 🌐 Step 2: Web Search - System searches the internet for relevant information 💡 Step 3: AI Analysis - AI analyzes search results and provides informed answer
Example flow:
- User asks: “What was the latest positive news story today?”
- AI thinks: “I need to search for recent positive news”
- System searches: Web for recent positive news stories
- Search returns: Recent articles about positive developments
- AI responds: “Today’s positive news includes [specific current story with source]”
🔧 Step 2: Adding Web Search to Your Backend
Section titled “🔧 Step 2: Adding Web Search to Your Backend”Let’s add web search to your existing backend using the same patterns you learned in previous modules. We’ll add new routes to handle web search-powered AI interactions.
Building on your foundation: You already have a working Node.js server with OpenAI integration. We’re simply adding web search capabilities to what you’ve built.
Step 2A: Understanding Web Search State
Section titled “Step 2A: Understanding Web Search State”Before writing code, let’s understand what data our web search system needs to manage:
// 🧠 WEB SEARCH STATE CONCEPTS:// 1. Search Queries - What the AI decides to search for// 2. Search Results - Information found on the web// 3. Source Attribution - Keeping track of where information came from// 4. Result Analysis - AI processing of search results// 5. Response Generation - Combining search data with AI reasoning
Key web search concepts:
- Query Generation: AI deciding what to search for based on user questions
- Search Execution: Using OpenAI’s web search tool to find information
- Result Processing: Analyzing and filtering search results
- Source Citation: Providing sources for information found
Step 2B: Adding the Web Search Route
Section titled “Step 2B: Adding the Web Search Route”Add this new endpoint to your existing index.js
file, right after your function calling routes:
// 🌐 WEB SEARCH ENDPOINT: Add this to your existing serverapp.post("/api/websearch/chat", async (req, res) => { try { // 🛡️ VALIDATION: Check required inputs const { message, context = "[]", includeSearch = true } = req.body;
if (!message?.trim()) { return res.status(400).json({ error: "Message is required", success: false }); }
console.log(`🌐 Web search chat: ${message}`);
// 📝 CONVERSATION CONTEXT: Parse existing conversation history let conversationHistory = []; try { conversationHistory = JSON.parse(context); } catch (error) { console.log("Starting new conversation"); }
// 🛠️ TOOLS SETUP: Define web search tool const tools = includeSearch ? [ { type: "web_search_preview" } ] : [];
// 🤖 AI WEB SEARCH: Process with OpenAI Response API const response = await openai.responses.create({ model: "gpt-4.1", tools: tools, input: [ { role: "system", content: includeSearch ? "You are a helpful AI assistant with access to real-time web search. When users ask about current events, recent information, or anything that might require up-to-date data, use web search to find accurate, current information. Always cite your sources when using search results." : "You are a helpful AI assistant. Answer questions using your training knowledge." }, ...conversationHistory, { role: "user", content: message.trim() } ] });
// 🔄 SEARCH RESULTS PROCESSING: Extract search information let searchResults = []; let finalResponse = response.output_text;
// Check if web search was used if (response.search_results && response.search_results.length > 0) { console.log(`🌐 AI used web search, found ${response.search_results.length} results`);
searchResults = response.search_results.map(result => ({ title: result.title || "No title", url: result.url || "", snippet: result.snippet || "No description available", timestamp: new Date().toISOString() })); }
// 🔄 CONVERSATION UPDATE: Update conversation history const updatedHistory = [ ...conversationHistory, { role: "user", content: message.trim() }, { role: "assistant", content: finalResponse } ];
// 📤 SUCCESS RESPONSE: Send web search results res.json({ success: true, message: finalResponse, search_used: searchResults.length > 0, search_results: searchResults, conversation_history: updatedHistory, model: "gpt-4.1", timestamp: new Date().toISOString() });
} catch (error) { // 🚨 ERROR HANDLING: Handle web search failures console.error("Web search error:", error);
res.status(500).json({ error: "Failed to process web search request", details: error.message, success: false }); }});
// 🔍 SEARCH TEST ENDPOINT: Test web search capabilityapp.post("/api/websearch/test", async (req, res) => { try { const { query = "positive news today" } = req.body;
console.log(`🌐 Testing web search with query: ${query}`);
const response = await openai.responses.create({ model: "gpt-4.1", tools: [{ type: "web_search_preview" }], input: `Search the web for: ${query}` });
res.json({ success: true, query: query, response: response.output_text, search_results: response.search_results || [], model: "gpt-4.1", timestamp: new Date().toISOString() });
} catch (error) { console.error("Web search test error:", error); res.status(500).json({ error: "Failed to test web search", details: error.message, success: false }); }});
// 📰 SEARCH SUGGESTIONS ENDPOINT: Get search suggestionsapp.get("/api/websearch/suggestions", (req, res) => { try { const suggestions = [ { category: "Current Events", queries: [ "What positive news happened today?", "Latest breakthrough in AI research", "Recent space exploration achievements", "Good news stories from this week" ] }, { category: "Real-time Data", queries: [ "Current Bitcoin price", "Today's weather in major cities", "Latest stock market performance", "Current exchange rates" ] }, { category: "Recent Developments", queries: [ "New technology announcements this month", "Recent scientific discoveries", "Latest movie releases and reviews", "Recent sports championship results" ] }, { category: "Trending Topics", queries: [ "What's trending on social media today?", "Popular viral videos this week", "Trending news topics right now", "Most discussed events recently" ] } ];
res.json({ success: true, suggestions: suggestions, count: suggestions.reduce((total, cat) => total + cat.queries.length, 0), timestamp: new Date().toISOString() });
} catch (error) { console.error("Search suggestions error:", error); res.status(500).json({ error: "Failed to get search suggestions", details: error.message, success: false }); }});
Function breakdown:
- Web search integration - Use OpenAI’s web_search_preview tool
- Message processing - Handle user requests with real-time search capability
- Search result extraction - Extract and format search results from AI responses
- Source attribution - Track sources and URLs for information found
- Conversation management - Maintain context with search-enhanced responses
Your backend now supports:
- Text chat (existing functionality)
- Streaming chat (existing functionality)
- Image generation (existing functionality)
- Audio transcription (existing functionality)
- File analysis (existing functionality)
- Text-to-speech (existing functionality)
- Vision analysis (existing functionality)
- Voice interaction (existing functionality)
- Function calling (existing functionality)
- Web search (new functionality)
🔧 Step 3: Building the React Web Search Component
Section titled “🔧 Step 3: Building the React Web Search Component”Now let’s create a React component for web search using the same patterns from your existing components.
Step 3A: Creating the Web Search Component
Section titled “Step 3A: Creating the Web Search Component”Create a new file src/WebSearch.jsx
:
import { useState, useRef, useEffect } from "react";import { Send, Search, Globe, ExternalLink, MessageSquare, Download, Trash2, Lightbulb } from "lucide-react";
function WebSearch() { // 🧠 STATE: Web search data management const [message, setMessage] = useState(""); // User input const [conversation, setConversation] = useState([]); // Chat history const [isProcessing, setIsProcessing] = useState(false); // Processing status const [searchEnabled, setSearchEnabled] = useState(true); // Search toggle const [searchResults, setSearchResults] = useState([]); // Recent search results const [suggestions, setSuggestions] = useState([]); // Search suggestions const [error, setError] = useState(null); // Error messages
const chatEndRef = useRef(null);
// 🔧 FUNCTIONS: Web search logic engine
// Load search suggestions on component mount useEffect(() => { loadSearchSuggestions(); }, []);
// Auto-scroll to bottom of chat useEffect(() => { chatEndRef.current?.scrollIntoView({ behavior: "smooth" }); }, [conversation]);
// Load search suggestions const loadSearchSuggestions = async () => { try { const response = await fetch("http://localhost:8000/api/websearch/suggestions"); const data = await response.json();
if (data.success) { setSuggestions(data.suggestions); } } catch (error) { console.error('Failed to load suggestions:', error); } };
// Send message with web search capability const sendMessage = async () => { if (!message.trim() || isProcessing) return;
const userMessage = message.trim(); setMessage(""); setIsProcessing(true); setError(null);
// Add user message to conversation immediately const newConversation = [ ...conversation, { role: "user", content: userMessage, timestamp: new Date().toISOString() } ]; setConversation(newConversation);
try { // 📤 API CALL: Send to web search endpoint const response = await fetch("http://localhost:8000/api/websearch/chat", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: userMessage, context: JSON.stringify(conversation), includeSearch: searchEnabled }), });
const data = await response.json();
if (!response.ok) { throw new Error(data.error || 'Failed to process message'); }
// ✅ SUCCESS: Update conversation and search results setConversation(data.conversation_history.map(msg => ({ ...msg, timestamp: msg.timestamp || new Date().toISOString() })));
// Track search results if any were found if (data.search_used && data.search_results && data.search_results.length > 0) { setSearchResults(prev => [...data.search_results, ...prev].slice(0, 20)); // Keep last 20 results }
} catch (error) { console.error('Web search failed:', error); setError(error.message || 'Something went wrong while processing your message');
// Add error message to conversation setConversation(prev => [...prev, { role: "assistant", content: "I'm sorry, I encountered an error while processing your request. Please try again.", timestamp: new Date().toISOString(), error: true }]); } finally { setIsProcessing(false); } };
// Send a suggested query const sendSuggestion = (query) => { setMessage(query); // Auto-send the suggestion setTimeout(() => { if (query.trim()) { setMessage(query); sendMessage(); } }, 100); };
// Test web search functionality const testWebSearch = async () => { setIsProcessing(true); setError(null);
try { const response = await fetch("http://localhost:8000/api/websearch/test", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query: "positive news today" }), });
const data = await response.json();
if (!response.ok) { throw new Error(data.error || 'Test failed'); }
// Add test results to conversation setConversation(prev => [...prev, { role: "user", content: "🧪 Test web search functionality", timestamp: new Date().toISOString() }, { role: "assistant", content: data.response, timestamp: new Date().toISOString(), test: true } ]);
// Add search results if (data.search_results && data.search_results.length > 0) { setSearchResults(prev => [...data.search_results, ...prev].slice(0, 20)); }
} catch (error) { console.error('Web search test failed:', error); setError(error.message || 'Web search test failed'); } finally { setIsProcessing(false); } };
// Handle Enter key press const handleKeyPress = (e) => { if (e.key === "Enter" && !e.shiftKey && !isProcessing) { e.preventDefault(); sendMessage(); } };
// Clear conversation const clearConversation = () => { setConversation([]); setSearchResults([]); setError(null); };
// Download conversation with search results const downloadConversation = () => { const exportData = { conversation: conversation, search_results: searchResults, search_enabled: searchEnabled, timestamp: new Date().toISOString() };
const element = document.createElement('a'); const file = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' }); element.href = URL.createObjectURL(file); element.download = `web-search-session-${Date.now()}.json`; document.body.appendChild(element); element.click(); document.body.removeChild(element); };
// 🎨 UI: Interface components return ( <div className="min-h-screen bg-gradient-to-br from-green-50 to-blue-50 flex items-center justify-center p-4"> <div className="bg-white rounded-2xl shadow-2xl w-full max-w-6xl flex flex-col overflow-hidden">
{/* Header */} <div className="bg-gradient-to-r from-green-600 to-blue-600 text-white p-6"> <div className="flex items-center justify-between"> <div className="flex items-center space-x-3"> <div className="w-10 h-10 bg-white bg-opacity-20 rounded-full flex items-center justify-center"> <Globe className="w-5 h-5" /> </div> <div> <h1 className="text-xl font-bold">🌐 AI Web Search</h1> <p className="text-green-100 text-sm">AI with real-time internet access!</p> </div> </div>
<div className="text-right"> <div className="flex items-center space-x-3"> <label className="flex items-center space-x-2 text-green-100"> <input type="checkbox" checked={searchEnabled} onChange={(e) => setSearchEnabled(e.target.checked)} className="rounded" /> <span className="text-sm">Web Search</span> </label> <button onClick={testWebSearch} disabled={isProcessing} className="px-3 py-1 bg-white bg-opacity-20 rounded-lg hover:bg-opacity-30 transition-colors duration-200 text-sm" > Test Search </button> </div> </div> </div> </div>
{/* Search Suggestions */} {conversation.length === 0 && suggestions.length > 0 && ( <div className="p-4 bg-gray-50 border-b border-gray-200"> <h3 className="font-semibold text-gray-900 mb-3 flex items-center text-sm"> <Lightbulb className="w-4 h-4 mr-2 text-green-600" /> Try These Web Search Examples </h3>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3"> {suggestions.slice(0, 2).map((category) => ( <div key={category.category} className="space-y-2"> <h4 className="font-medium text-gray-700 text-xs">{category.category}</h4> {category.queries.slice(0, 2).map((query, idx) => ( <button key={idx} onClick={() => sendSuggestion(query)} disabled={isProcessing} className="w-full text-left p-2 bg-white rounded border border-gray-200 hover:border-green-300 hover:bg-green-50 transition-colors duration-200 text-xs" > {query} </button> ))} </div> ))} </div> </div> )}
{/* Chat Area */} <div className="flex-1 flex flex-col min-h-0"> <div className="flex-1 overflow-y-auto p-6 space-y-4"> {conversation.length === 0 ? ( <div className="text-center py-12"> <div className="w-16 h-16 bg-green-100 rounded-2xl flex items-center justify-center mx-auto mb-4"> <Globe className="w-8 h-8 text-green-600" /> </div> <h3 className="text-lg font-semibold text-gray-700 mb-2"> Ready for Web Search! </h3> <p className="text-gray-600 max-w-md mx-auto mb-4"> Ask me about current events, recent news, or anything that requires up-to-date information. </p> <div className="text-sm text-gray-500 space-y-1"> <p>💡 "What positive news happened today?"</p> <p>💡 "Current Bitcoin price"</p> <p>💡 "Latest AI research breakthroughs"</p> </div> </div> ) : ( <> {conversation.map((msg, index) => ( <div key={index} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`} > <div className={`max-w-3xl px-4 py-3 rounded-lg ${ msg.role === 'user' ? 'bg-green-500 text-white' : msg.error ? 'bg-red-50 text-red-700 border border-red-200' : msg.test ? 'bg-blue-50 text-blue-700 border border-blue-200' : 'bg-gray-100 text-gray-900' }`} > <p className="whitespace-pre-wrap">{msg.content}</p> <p className="text-xs opacity-70 mt-1"> {new Date(msg.timestamp).toLocaleTimeString()} {msg.test && " • Test"} </p> </div> </div> ))}
{isProcessing && ( <div className="flex justify-start"> <div className="bg-gray-100 text-gray-900 px-4 py-3 rounded-lg"> <div className="flex items-center space-x-2"> <Search className="w-4 h-4 text-green-600 animate-spin" /> <span className="text-sm">Searching the web and analyzing results...</span> </div> </div> </div> )} <div ref={chatEndRef} /> </> )} </div>
{/* Search Results Log */} {searchResults.length > 0 && ( <div className="border-t border-gray-200 p-4 bg-gray-50"> <h4 className="font-semibold text-gray-900 mb-2 text-sm flex items-center"> <Search className="w-4 h-4 mr-2 text-green-600" /> Recent Search Results ({searchResults.length}) </h4> <div className="space-y-2 max-h-32 overflow-y-auto"> {searchResults.slice(0, 3).map((result, index) => ( <div key={index} className="bg-white rounded p-2 border border-gray-200 text-xs"> <div className="flex items-start justify-between"> <div className="flex-1"> <h5 className="font-medium text-gray-900 mb-1">{result.title}</h5> <p className="text-gray-600 text-xs">{result.snippet}</p> {result.url && ( <a href={result.url} target="_blank" rel="noopener noreferrer" className="text-green-600 hover:text-green-700 text-xs flex items-center mt-1" > <ExternalLink className="w-3 h-3 mr-1" /> {new URL(result.url).hostname} </a> )} </div> </div> </div> ))} </div> </div> )}
{/* Error Display */} {error && ( <div className="border-t border-red-200 bg-red-50 p-4"> <p className="text-red-700 text-sm"> <strong>Error:</strong> {error} </p> </div> )}
{/* Input Area */} <div className="border-t border-gray-200 p-4"> <div className="flex items-center space-x-3"> <div className="flex-1"> <textarea value={message} onChange={(e) => setMessage(e.target.value)} onKeyPress={handleKeyPress} rows="2" placeholder={searchEnabled ? "Ask about current events, recent news, or real-time information..." : "Ask me anything (web search disabled)..."} disabled={isProcessing} className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent transition-all duration-200 resize-none disabled:bg-gray-100" /> </div> <div className="space-y-2"> <button onClick={sendMessage} disabled={isProcessing || !message.trim()} className="px-6 py-3 bg-gradient-to-r from-green-600 to-blue-600 hover:from-green-700 hover:to-blue-700 disabled:from-gray-300 disabled:to-gray-300 text-white rounded-lg transition-all duration-200 flex items-center space-x-2 shadow-lg disabled:shadow-none" > <Send className="w-4 h-4" /> <span>Send</span> </button>
{conversation.length > 0 && ( <div className="flex space-x-1"> <button onClick={downloadConversation} className="p-2 bg-gray-100 text-gray-600 rounded-lg hover:bg-gray-200 transition-colors duration-200" title="Download conversation" > <Download className="w-4 h-4" /> </button> <button onClick={clearConversation} className="p-2 bg-red-100 text-red-600 rounded-lg hover:bg-red-200 transition-colors duration-200" title="Clear conversation" > <Trash2 className="w-4 h-4" /> </button> </div> )} </div> </div> </div> </div> </div> </div> );}
export default WebSearch;
Step 3B: Adding Web Search to Navigation
Section titled “Step 3B: Adding Web Search to Navigation”Update your src/App.jsx
to include the new web search component:
import { useState } from "react";import StreamingChat from "./StreamingChat";import ImageGenerator from "./ImageGenerator";import AudioTranscription from "./AudioTranscription";import FileAnalysis from "./FileAnalysis";import TextToSpeech from "./TextToSpeech";import VisionAnalysis from "./VisionAnalysis";import VoiceInteraction from "./VoiceInteraction";import FunctionCalling from "./FunctionCalling";import WebSearch from "./WebSearch";import { MessageSquare, Image, Mic, Folder, Volume2, Eye, Phone, Zap, Globe } from "lucide-react";
function App() { // 🧠 STATE: Navigation management const [currentView, setCurrentView] = useState("chat"); // Add 'websearch' option
// 🎨 UI: Main app with navigation return ( <div className="min-h-screen bg-gray-100"> {/* Navigation Header */} <nav className="bg-white shadow-sm border-b border-gray-200"> <div className="max-w-7xl mx-auto px-4"> <div className="flex items-center justify-between h-16"> {/* Logo */} <div className="flex items-center space-x-3"> <div className="w-8 h-8 bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg flex items-center justify-center"> <span className="text-white font-bold text-sm">AI</span> </div> <h1 className="text-xl font-bold text-gray-900">OpenAI Mastery</h1> </div>
{/* Navigation Buttons */} <div className="flex space-x-1 overflow-x-auto"> <button onClick={() => setCurrentView("chat")} className={`px-2 py-2 rounded-lg flex items-center space-x-1 transition-all duration-200 whitespace-nowrap text-sm ${ currentView === "chat" ? "bg-blue-100 text-blue-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <MessageSquare className="w-4 h-4" /> <span>Chat</span> </button>
<button onClick={() => setCurrentView("images")} className={`px-2 py-2 rounded-lg flex items-center space-x-1 transition-all duration-200 whitespace-nowrap text-sm ${ currentView === "images" ? "bg-purple-100 text-purple-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Image className="w-4 h-4" /> <span>Images</span> </button>
<button onClick={() => setCurrentView("audio")} className={`px-2 py-2 rounded-lg flex items-center space-x-1 transition-all duration-200 whitespace-nowrap text-sm ${ currentView === "audio" ? "bg-blue-100 text-blue-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Mic className="w-4 h-4" /> <span>Audio</span> </button>
<button onClick={() => setCurrentView("files")} className={`px-2 py-2 rounded-lg flex items-center space-x-1 transition-all duration-200 whitespace-nowrap text-sm ${ currentView === "files" ? "bg-green-100 text-green-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Folder className="w-4 h-4" /> <span>Files</span> </button>
<button onClick={() => setCurrentView("speech")} className={`px-2 py-2 rounded-lg flex items-center space-x-1 transition-all duration-200 whitespace-nowrap text-sm ${ currentView === "speech" ? "bg-orange-100 text-orange-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Volume2 className="w-4 h-4" /> <span>Speech</span> </button>
<button onClick={() => setCurrentView("vision")} className={`px-2 py-2 rounded-lg flex items-center space-x-1 transition-all duration-200 whitespace-nowrap text-sm ${ currentView === "vision" ? "bg-indigo-100 text-indigo-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Eye className="w-4 h-4" /> <span>Vision</span> </button>
<button onClick={() => setCurrentView("voice")} className={`px-2 py-2 rounded-lg flex items-center space-x-1 transition-all duration-200 whitespace-nowrap text-sm ${ currentView === "voice" ? "bg-blue-100 text-blue-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Phone className="w-4 h-4" /> <span>Voice</span> </button>
<button onClick={() => setCurrentView("functions")} className={`px-2 py-2 rounded-lg flex items-center space-x-1 transition-all duration-200 whitespace-nowrap text-sm ${ currentView === "functions" ? "bg-cyan-100 text-cyan-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Zap className="w-4 h-4" /> <span>Functions</span> </button>
<button onClick={() => setCurrentView("websearch")} className={`px-2 py-2 rounded-lg flex items-center space-x-1 transition-all duration-200 whitespace-nowrap text-sm ${ currentView === "websearch" ? "bg-green-100 text-green-700 shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100" }`} > <Globe className="w-4 h-4" /> <span>Web</span> </button> </div> </div> </div> </nav>
{/* Main Content */} <main className="h-[calc(100vh-4rem)]"> {currentView === "chat" && <StreamingChat />} {currentView === "images" && <ImageGenerator />} {currentView === "audio" && <AudioTranscription />} {currentView === "files" && <FileAnalysis />} {currentView === "speech" && <TextToSpeech />} {currentView === "vision" && <VisionAnalysis />} {currentView === "voice" && <VoiceInteraction />} {currentView === "functions" && <FunctionCalling />} {currentView === "websearch" && <WebSearch />} </main> </div> );}
export default App;
🧪 Testing Your Web Search
Section titled “🧪 Testing Your Web Search”Let’s test your web search feature step by step to make sure everything works correctly.
Step 1: Backend Route Test
Section titled “Step 1: Backend Route Test”First, verify your backend routes work:
Test web search endpoint:
curl -X POST http://localhost:8000/api/websearch/chat \ -H "Content-Type: application/json" \ -d '{"message": "What positive news happened today?", "includeSearch": true}'
Test search suggestions endpoint:
curl http://localhost:8000/api/websearch/suggestions
Step 2: Full Application Test
Section titled “Step 2: Full Application Test”Start both servers:
Backend (in your backend folder):
npm run dev
Frontend (in your frontend folder):
npm run dev
Test the complete flow:
- Navigate to Web Search → Click the “Web” tab in navigation
- Review search suggestions → See example queries for current events
- Test current events → Ask “What positive news happened today?”
- Test real-time data → Ask “Current Bitcoin price”
- Test recent information → Ask “Latest AI research breakthroughs”
- Try search suggestions → Click on suggested queries
- Toggle search on/off → Disable web search and see difference
- Review search results → See sources and URLs for information found
- Download conversation → Export chat with search results
Step 3: Error Handling Test
Section titled “Step 3: Error Handling Test”Test error scenarios:
❌ Search disabled: Turn off web search and ask about current events❌ Network error: Disconnect internet during search❌ Invalid query: Send empty or malformed messages❌ Rate limiting: Send multiple rapid requests
Expected behavior:
- Clear indication when search is enabled/disabled
- Graceful fallback when search fails
- Source attribution for all search results
- Proper error messages for issues
✅ What You Built
Section titled “✅ What You Built”Congratulations! You’ve extended your existing application with complete AI web search:
- ✅ Extended your backend with OpenAI web search tool integration
- ✅ Added React web search component following the same patterns as your other features
- ✅ Implemented real-time internet access for current information and events
- ✅ Created search result tracking with source attribution and URLs
- ✅ Added search suggestions with categorized example queries
- ✅ Maintained consistent design with your existing application
Your application now has:
- Text chat with streaming responses
- Image generation with DALL-E 3 and GPT-Image-1
- Audio transcription with Whisper voice recognition
- File analysis with intelligent document processing
- Text-to-speech with natural voice synthesis
- Vision analysis with GPT-4o visual intelligence
- Voice interaction with GPT-4o Audio natural conversations
- Function calling with real-world tool integration
- Web search with real-time internet access
- Unified navigation between all features
- Professional UI with consistent TailwindCSS styling
Next up: You’ll learn about MCP Integration, where your AI can connect to remote Model Context Protocol servers to access specialized tools and data sources.
Your OpenAI mastery application now has real-time internet access! 🌐