This roadmap provides a comprehensive, step-by-step plan for building a production-grade AI-powered knowledge workspace with document ingestion, semantic search, and LLM-powered chat capabilities.
- Create Next.js 14 project with TypeScript
- Command:
npx create-next-app@latest . --typescript --tailwind --app --no-src-dir - Configure: App Router, TypeScript strict mode
- Command:
- Install core dependencies
- React 18, Next.js 14
- TypeScript, ESLint, Prettier
- Set up project structure
/app /(auth) /(dashboard) /api /components /ui (shadcn components) /lib /types /hooks /utils
- Install and configure TailwindCSS
- Initialize shadcn/ui
- Command:
npx shadcn-ui@latest init - Configure: TypeScript, TailwindCSS, App Router
- Command:
- Install base shadcn components
- Button, Input, Card, Dialog, Sheet, Tabs, Avatar, Badge, Progress, ScrollArea, Separator, Skeleton, Toast (Sonner)
- Set up theme configuration (light/dark mode)
- Create layout components (Header, Sidebar, Footer)
- Create
.env.localtemplate- Next.js variables
- Supabase credentials
- API keys (OpenAI, Anthropic, Groq, VoyageAI)
- Set up
.env.examplewith placeholder values - Configure environment variable validation with Zod
- Initialize git repository (if not exists)
- Create
.gitignore(Next.js, node_modules, .env.local) - Set up initial commit structure
- Create development branch strategy
- Create Supabase project
- Get project URL and anon key
- Install Supabase client libraries
@supabase/supabase-js@supabase/ssr(for Next.js)
- Configure Supabase client utilities
- Create
/lib/supabase/client.ts(browser client) - Create
/lib/supabase/server.ts(server client) - Create
/lib/supabase/middleware.ts(middleware client)
- Create
- Enable
pgvectorextension in Supabase SQL editorCREATE EXTENSION IF NOT EXISTS vector;
- Verify extension installation
- Create
profilestableCREATE TABLE profiles ( id UUID PRIMARY KEY REFERENCES auth.users(id), email TEXT, full_name TEXT, avatar_url TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() );
- Set up Row Level Security (RLS) policies
- Create trigger for automatic profile creation on signup
- Create
documentstableCREATE TABLE documents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, title TEXT NOT NULL, file_name TEXT, file_type TEXT, file_size BIGINT, storage_path TEXT, status TEXT DEFAULT 'pending', -- pending, processing, completed, failed metadata JSONB, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() );
- Add RLS policies (users can only access their own documents)
- Create indexes on
user_id,status - Create index on
created_at(not yet implemented)
- Create
document_chunkstableCREATE TABLE document_chunks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), document_id UUID REFERENCES documents(id) ON DELETE CASCADE, user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, chunk_index INTEGER NOT NULL, content TEXT NOT NULL, content_tokens INTEGER, embedding vector(1536), -- Adjust based on embedding model metadata JSONB, created_at TIMESTAMPTZ DEFAULT NOW() );
- Add RLS policies
- Create vector index for similarity search
CREATE INDEX ON document_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
- Create indexes on
document_id,user_id - Create index on
chunk_index(not yet implemented)
- Create
conversationstableCREATE TABLE conversations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, title TEXT, model_provider TEXT, -- openai, anthropic, groq model_name TEXT, system_prompt TEXT, temperature DECIMAL(3,2) DEFAULT 0.7, use_memory BOOLEAN DEFAULT true, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() );
- Add RLS policies
- Create indexes on
user_id,created_at
- Create
messagestableCREATE TABLE messages ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE, user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, role TEXT NOT NULL, -- user, assistant, system content TEXT NOT NULL, tokens_used INTEGER, model_used TEXT, latency_ms INTEGER, retrieved_chunk_ids UUID[], metadata JSONB, created_at TIMESTAMPTZ DEFAULT NOW() );
- Add RLS policies
- Create indexes on
conversation_id,user_id,created_at
- Create
eval_logstableCREATE TABLE eval_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE, message_id UUID REFERENCES messages(id) ON DELETE CASCADE, request_data JSONB, response_data JSONB, tokens_input INTEGER, tokens_output INTEGER, provider TEXT, model TEXT, latency_ms INTEGER, error TEXT, created_at TIMESTAMPTZ DEFAULT NOW() );
- Add RLS policies
- Create indexes on
user_id,created_at - Create index on
provider(not yet implemented)
- Create storage bucket:
documents - Configure bucket policies (authenticated users can upload/read their own files)
- Set up storage RLS policies
- Configure file size limits and allowed types
- Create function to update
updated_attimestamp - Create trigger for
documents.updated_at - Create trigger for
conversations.updated_at - Create function to count chunks per document (chunk_count column exists but no function)
- Create function to get conversation token usage
- Install Drizzle ORM:
npm install drizzle-orm drizzle-kit @supabase/supabase-js - Create
/lib/db/schema.tswith all table definitions - Create
/lib/db/index.tsfor database client - Set up Drizzle migrations
- Generate initial migration from schema
- Configure Supabase Auth settings (email/password enabled)
- Enable email/password
- Enable magic link (UI implemented, see auth-form.tsx)
- Configure OAuth providers (Google, GitHub) if needed
- Set up email templates
- Configure redirect URLs for auth callbacks (implemented in auth-form.tsx)
- Create
/app/(auth)/login/page.tsx- Email/password form
- Magic link option (implemented in auth-form.tsx)
- OAuth buttons (if enabled)
- Error handling
- Create
/app/(auth)/signup/page.tsx- Registration form
- Terms acceptance
- Email verification notice
- Create
/app/(auth)/callback/route.tsfor auth callback handling - Create
/app/(auth)/logout/route.tsfor logout
- Create
/middleware.tsfor route protection- Protect dashboard routes
- Redirect unauthenticated users to login
- Handle auth token refresh
- Create
/lib/auth/get-user.tsutility - Create
/lib/auth/require-auth.tsutility for server components
- Create
/app/(dashboard)/settings/profile/page.tsx- Display user info
- Update profile form
- Avatar upload
- Create API route:
/api/user/profile/route.ts- GET: Fetch user profile
- PATCH: Update user profile
- Create
/components/documents/upload-zone.tsx- Drag-and-drop area
- File input
- File type validation (PDF, TXT)
- File size validation
- Multiple file support
- Upload progress indicator
- Create
/components/documents/upload-button.tsx - Integrate with shadcn Dialog/Sheet for upload modal
- Create
/app/actions/documents/upload.ts- Validate file type and size
- Generate unique file name
- Upload to Supabase Storage
- Create document record in database
- Return document ID
- Add error handling and validation
- Create URL input component (integrated into
/components/documents/upload-document-button.tsx)- URL input form
- URL validation
- Create
/app/actions/documents/ingest-url.ts(implemented asingestUrlfunction inupload.ts)- Fetch URL content
- Extract text (using cheerio - see
lib/ingestion/url-ingestion.ts) - Create document record
- Trigger ingestion pipeline
- Create
/components/documents/document-list.tsx- Display documents in table/card view
- Show: name, size, upload date, status
- Status badges (pending, processing, completed, failed)
- Create
/components/documents/document-card.tsx - Add pagination
- Add filtering by status
- Add sorting options
- Create
/app/actions/documents/delete.ts- Delete from storage
- Delete from database (cascade to chunks)
- Create
/app/actions/documents/reindex.ts- Reset document status
- Trigger re-ingestion
- Add confirmation dialogs for destructive actions
- Install PDF parsing library
- Option A:
pdf-parse - Option B:
pdfjs-dist(PDF.js) - Option C:
llama-parse(if available)
- Option A:
- Create
/lib/ingestion/pdf-parser.ts- Extract text from PDF
- Handle multi-page documents
- Extract metadata (title, author, pages)
- Error handling for corrupted PDFs
- Create
/lib/ingestion/text-processor.ts(text processing is integrated into chunker.ts and pipeline.ts)- Normalize whitespace (handled in pipeline)
- Remove special characters (optional)
- Split into paragraphs (handled in chunker)
- Calculate token counts (handled in chunker with tiktoken)
- Create
/lib/ingestion/chunker.ts- Implement recursive chunking
- Configurable chunk size (tokens/characters)
- Overlap between chunks
- Preserve sentence boundaries
- Handle markdown/structured text
- Create chunking utilities
- Token counting (tiktoken or similar)
- Text splitting with overlap
- Metadata preservation per chunk
- Install embedding libraries
- OpenAI SDK:
openai - VoyageAI SDK (if using)
- HuggingFace transformers (if using BAAI/bge)
- OpenAI SDK:
- Create
/lib/embeddings/openai.ts- Generate embeddings using OpenAI
text-embedding-3-smallortext-embedding-ada-002 - Batch processing support
- Error handling and retries
- Generate embeddings using OpenAI
- Create
/lib/embeddings/voyage.ts(optional) - Create
/lib/embeddings/huggingface.ts(optional) - Create
/lib/embeddings/index.ts(unified interface)
- Create
/app/api/documents/[id]/ingest/route.ts(implemented as/app/api/ingestion/process/route.ts)- Accept document ID
- Fetch document from storage
- Parse document (PDF/text)
- Chunk content
- Generate embeddings (batch)
- Store chunks in database with vectors
- Update document status
- Return ingestion result
- Add progress tracking (optional: WebSocket or polling)
- Set up background job processing
- Option A: Vercel Cron Jobs
- Option B: Queue system (BullMQ, etc.)
- Create ingestion queue worker
- Handle retries and failures
- Create real-time status updates using Supabase Realtime
- Update UI when document status changes
- Show progress bar during ingestion
- Create
/lib/vector/search.ts- Function to generate query embedding
- Function to perform similarity search
- Configurable top-k results
- Filter by user_id and document_id
- Return chunks with similarity scores
- Create
/app/api/search/route.ts- Accept query string
- Generate query embedding
- Perform vector search
- Return results with metadata
- Include document references
- Implement keyword + vector hybrid search
- Combine BM25 and vector similarity scores
- Create
/lib/vector/hybrid-search.ts
- Create
/app/(dashboard)/chat/page.tsx- Main chat interface layout
- Sidebar for conversations
- Main chat area
- Sources panel
- Create responsive layout (mobile-friendly)
- Create
/components/chat/conversation-list.tsx- List of user conversations
- Conversation titles
- Last message preview
- Timestamp
- Create new conversation button
- Create
/components/chat/conversation-item.tsx - Add conversation search/filter
- Create
/components/chat/message-list.tsx- Display messages in chronological order
- User messages (right-aligned)
- Assistant messages (left-aligned)
- Streaming message support
- Markdown rendering for assistant messages
- Create
/components/chat/message-bubble.tsx - Create
/components/chat/message-avatar.tsx - Add copy button for messages
- Add timestamp display
- Create
/components/chat/chat-input.tsx- Textarea with auto-resize
- Send button
- Keyboard shortcuts (Enter to send, Shift+Enter for new line)
- Character/token counter (optional)
- Disable during streaming
- Create
/components/chat/input-toolbar.tsx(settings are loaded from user settings, not in toolbar)- Model selector
- Temperature slider
- Settings button
- Streaming implemented directly in
/components/chat/chat-interface.tsx(no separate stream-handler.ts)- Handle Server-Sent Events (SSE)
- Parse streaming chunks
- Update UI incrementally
- Streaming logic implemented in chat-interface.tsx (no separate use-chat-stream hook)
- React hook for streaming
- State management
- Error handling
- Create
/components/chat/sources-panel.tsx- Display retrieved chunks
- Show document names
- Highlight relevant text
- Link to source documents
- Collapsible/expandable
- Create
/app/api/chat/route.ts- Accept POST request with:
- conversation_id (or create new)
- message content
- model preferences
- Retrieve conversation history
- Perform RAG retrieval
- Build prompt with context
- Call LLM provider
- Stream response
- Save messages to database
- Log evaluation data
- Accept POST request with:
- Create
/lib/rag/retrieve.ts(integrated into chat API route)- Generate query embedding
- Perform vector search (top-k)
- Filter by user's documents
- Rank and re-rank results
- Format chunks for prompt
- Create
/lib/rag/prompt-builder.ts- System prompt template
- Context injection
- Conversation history formatting
- Token counting
- Context window management
- Create
/lib/llm/openai.ts- Initialize OpenAI client
- Chat completion with streaming
- Handle errors and retries
- Token counting
- Create
/lib/llm/anthropic.ts- Initialize Anthropic client
- Messages API with streaming
- Handle errors and retries
- Create
/lib/llm/groq.ts- Initialize Groq client
- Ultra-low-latency inference
- Model selection (Llama 3, Mixtral)
- Create
/lib/llm/index.ts- Unified interface for all providers
- Provider selection logic
- Fallback mechanism
- Consistent response format
- Create
/lib/chat/memory.ts- Fetch conversation history
- Manage context window
- Summarize old messages (optional)
- Maintain conversation state
- Create
/lib/chat/save-message.ts- Save user message
- Save assistant message
- Update conversation timestamp
- Handle errors
- Create
/app/(dashboard)/search/page.tsx- Search input
- Results display
- Filters (by document, date range)
- Create
/components/search/search-bar.tsx - Create
/components/search/search-filters.tsx
- Create
/components/search/search-results.tsx- Display matched chunks
- Highlight matching text
- Show similarity scores
- Document references
- Pagination
- Create
/components/search/result-item.tsx - Create
/components/search/result-highlight.tsx
- Connect search UI to search API
- Add debouncing for search input (not yet implemented)
- Add loading states
- Add empty states
- Create
/lib/analytics/logger.ts- Log request/response
- Log tokens used
- Log latency
- Log provider/model
- Log errors
- Create
/lib/analytics/log-eval.ts(implemented as logger.ts)- Save to eval_logs table
- Batch logging support
- Create
/app/(dashboard)/analytics/page.tsx- Overview dashboard
- Charts/graphs (using recharts or similar)
- Metrics display
- Create
/components/analytics/metrics-card.tsx - Create
/components/analytics/usage-chart.tsx
- Create
/lib/analytics/queries.ts- Messages per session
- Token usage over time
- Model response latency
- Provider usage distribution
- Error rates
- Create
/app/api/analytics/usage/route.ts- GET: Fetch usage statistics
- Date range filtering
- Create
/app/api/analytics/tokens/route.ts- GET: Fetch token usage
- Create
/app/api/analytics/latency/route.ts- GET: Fetch latency metrics
- Create
/app/(dashboard)/settings/page.tsx- Tabs for different settings sections
- Model selection (implemented with Select component)
- Temperature control (implemented with Slider component)
- System prompt editor (implemented with Textarea component)
- Memory toggle
- Model selector (integrated into settings page with Select component)
- Temperature slider (integrated into settings page with Slider component)
- System prompt editor (integrated into settings page with Textarea component)
- Create
/app/actions/settings/update.ts- Save user preferences
- Update conversation defaults
- Create settings storage (database or localStorage)
- Create
/lib/settings/get-settings.ts
- Add preferences table (optional) or use JSONB in profiles
- Store: theme, default model, default temperature, etc.
- Load preferences on app initialization
- Create
/app/(dashboard)/page.tsx- Welcome message
- Quick stats (document count, total chunks, conversations) - basic welcome page only
- Recent documents (not yet implemented)
- Recent conversations (not yet implemented)
- Quick actions (not yet implemented)
- Create
/components/dashboard/stats-grid.tsx - Create
/components/dashboard/recent-activity.tsx
- Create
/components/layout/sidebar.tsx- Navigation links
- User menu
- Logout button
- Create
/components/layout/header.tsx- App title/logo
- User avatar
- Notifications (optional)
- Create
/components/layout/main-layout.tsx- Combine header, sidebar, main content
- Responsive design
- Create
/components/empty-states/no-documents.tsx(integrated into document-list) - Create
/components/empty-states/no-conversations.tsx - Create
/components/empty-states/no-search-results.tsx(integrated into search-results)
- Create
/components/error-boundary.tsx- Catch React errors
- Display user-friendly error messages
- Log errors
- Wrap app with error boundary
- Create
/lib/errors/api-error.ts- Standardized error format
- Error codes
- User-friendly messages
- Add error handling to all API routes
- Add error handling to Server Actions
- Create
/components/loading/spinner.tsx - Create
/components/loading/skeleton.tsx - Add loading states to all async operations
- Add Zod schemas for all inputs
- Validate file uploads
- Validate API requests
- Validate forms
- Implement dynamic imports for heavy components
- Lazy load chat interface
- Lazy load analytics charts
- Implement React Server Component caching
- Add caching headers to API routes
- Cache embeddings (optional)
- Use Vercel KV for session caching (optional)
- Review and optimize database queries
- Add missing indexes
- Optimize vector search queries
- Implement query result pagination
- Analyze bundle size
- Remove unused dependencies
- Optimize imports
- Use tree-shaking
- Set up Jest and React Testing Library
- Test utility functions
- Test components
- Test hooks
- Test API routes
- Test Server Actions
- Test database operations
- Set up Playwright or Cypress
- Test user flows:
- Sign up → Upload document → Chat
- Search → View results
- Settings → Update preferences
- Connect GitHub repository to Vercel
- Configure environment variables
- Set up build settings
- Deploy to production
- Configure custom domain (optional)
- Verify production database
- Run migrations
- Configure production storage buckets
- Set up production auth settings
- Configure CORS and security settings
- Set up error tracking (Sentry or similar)
- Set up analytics (PostHog or Vercel Analytics)
- Monitor API performance
- Set up alerts for errors
- Write README.md with setup instructions
- Document environment variables
- Document API endpoints
- Create user guide (optional)
- Review all pages for consistency
- Ensure responsive design works on all devices
- Add animations and transitions
- Improve loading states
- Add tooltips and help text
- Add ARIA labels
- Ensure keyboard navigation
- Test with screen readers
- Ensure color contrast
- Review RLS policies
- Review API authentication
- Review file upload security
- Review XSS prevention
- Review CSRF protection
- Load testing for API routes
- Test with large documents
- Test with many conversations
- Optimize slow queries
Week 1: Foundation
- Phase 1: Project Setup
- Phase 2: Supabase & Database
- Phase 3: Authentication
Week 2: Core Features
- Phase 4: Document Upload
- Phase 5: Ingestion Pipeline
- Phase 6: Vector Search
Week 3: Chat & Search
- Phase 7: Chat Frontend
- Phase 8: RAG Backend
- Phase 9: Semantic Search UI
Week 4: Polish & Deploy
- Phase 10: Analytics
- Phase 11: Settings
- Phase 12: Dashboard
- Phase 13-17: Error Handling, Optimization, Testing, Deployment
- Phase 2 → Phase 3: Database must exist before auth
- Phase 2 → Phase 4: Documents table needed for upload
- Phase 4 → Phase 5: Upload must work before ingestion
- Phase 5 → Phase 6: Chunks must exist before search
- Phase 6 → Phase 8: Vector search needed for RAG
- Phase 7 → Phase 8: Frontend needs backend API
- Phase 8 → Phase 10: Chat must work before analytics
- Each phase should be completed and tested before moving to the next
- Use feature flags for incomplete features
- Commit frequently with descriptive messages
- Test on multiple browsers and devices
- Keep security and performance in mind throughout
- Minimum Viable Product (MVP): 3-4 weeks
- Full Production Version: 6-8 weeks
- With Testing & Polish: 8-10 weeks
This roadmap is designed to be followed sequentially, but some phases can be worked on in parallel with proper coordination.