A Next.js 15 + TypeScript web application that combines web search with AI-powered responses for research assistance.
- Web Search Integration: Uses Exa.ai API for real-time web search
- AI-Powered Responses: Streams responses from OpenRouter API
- Multiple Response Styles: Default, step-by-step, bullet summary, and "explain like I'm 5"
- Real-time Streaming: Token-by-token response streaming
- Modern UI: Built with shadcn/ui and Tailwind CSS
- State Management: Zustand for global state
- Input Validation: Zod schemas for type-safe validation
- Next.js 15 with App Router
- TypeScript for type safety
- shadcn/ui for UI components
- Tailwind CSS for styling
- Zustand for state management
- Zod for validation
- Exa.ai API for web search
- OpenRouter API for LLM streaming
-
Install dependencies:
npm install
-
Set up environment variables: Create a
.envfile in the root directory:EXA_API_KEY=your_exa_api_key_here OPENROUTER_API_KEY=your_openrouter_api_key_here
-
Get API keys:
- Exa.ai: Sign up at exa.ai for free credits
- OpenRouter: Sign up at openrouter.ai for API access
-
Run the development server:
npm run dev
-
Open your browser: Navigate to http://localhost:3000
- Ask a research question in the text area
- Select a response style from the dropdown:
- Default: Comprehensive response
- Step-by-step: Numbered steps
- Bullet Summary: Key points
- Explain Like I'm 5: Simple explanation
- Click submit to start the research process
- Watch the response stream in real-time
- Generate questions related to context
- Copy responses or individual highlights
- Manage bookmarks in the sidebar
├── app/
│ ├── api/
│ │ ├── search/route.ts # Exa.ai search endpoint
│ │ └── stream/route.ts # OpenRouter streaming endpoint
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout
│ └── page.tsx # Main page
├── components/
│ ├── ui/ # shadcn/ui components
│ ├── Chat.tsx # Chat interface
│ ├── InputBox.tsx # Input form
│ ├── HighlightsSidebar.tsx # Highlights management
│ └── TypingIndicator.tsx # Loading animation
├── lib/
│ ├── api.ts # API wrapper functions
│ ├── store.ts # Zustand store
│ ├── utils.ts # Utility functions
│ └── validators.ts # Zod schemas
└── package.json
- Searches the web for relevant information
- Returns structured results with titles, URLs, and content
- Used to provide context for AI responses
- Streams AI responses token-by-token
- Uses GPT-3.5-turbo model
- Combines user query with web search context
User Query → Web Search → Context Preparation → AI Generation → Streaming Response
Step-by-step:
- User Input: User types question in InputBox.tsx
- Search Trigger: Chat.tsx calls searchWithExa()
- Web Search: /api/search → Exa.ai API → Neural web search
- Context Formatting: formatSearchContext() creates structured context
- AI Processing: /api/stream → OpenRouter API with context + query
- Streaming Response: GPT-3.5-turbo streams tokens back
- UI Updates: Real-time display with source citations
- Streaming Implementation: Robust token-by-token streaming with proper error handling
- API Integration: Clean separation between Exa.ai search and OpenRouter streaming
- State Management: Zustand provides excellent state persistence and management
- UI/UX: Modern, responsive design with great user experience
- Type Safety: Full TypeScript implementation with Zod validation
- Error Handling: Comprehensive error handling throughout the application
- Streaming Complexity: Managing multiple streaming formats (AI SDK UI vs original format)
- State Synchronization: Keeping UI in sync with streaming responses
- API Rate Limits: Managing Exa.ai and OpenRouter API limits
- Timeout Handling: Ensuring streams complete properly with 30-second timeouts
- UI is smooth and easy to use.
- As of now we have allowed for singel user, we can add a new feature for teams
- TypeScript: Full type safety throughout the application
- ESLint: Code linting and formatting
- Tailwind CSS: Utility-first CSS framework
- Responsive Design: Works on desktop and mobile devices
