-
Notifications
You must be signed in to change notification settings - Fork 155
Description
Problem Statement
Currently, the AI chat application stores conversations only in memory (via InMemoryConversationRepository), which means:
- No persistence: All chat history is lost when the user closes the tab or refreshes the page
- No conversation management: Users cannot view, switch between, or manage past conversations
- Limited user value: Users must re-explain context in every new session
The application has a well-designed hexagonal architecture with domain entities and repository interfaces already in place, but lacks a persistent storage adapter and UI for conversation management.
User Value
For end users:
- Never lose conversations: All chat history is automatically saved to MongoDB and persists across sessions
- Easy access: View and switch between past conversations via a collapsible sidebar
- Better organization: Filter conversations by status (Active/Archived), see timestamps, and manage old conversations
- Improved productivity: Resume previous conversations without re-explaining context
Concrete examples:
- A user researching a topic can return the next day and continue where they left off
- A user can switch between multiple ongoing conversations (e.g., one for coding help, another for weather queries)
- A user can archive old conversations to declutter their workspace while keeping history intact
Architecture Overview
This feature requires implementing both backend and frontend components following the existing hexagonal architecture:
Backend (src/infrastructure/adapters/database/):
MongoDBClient.ts- Singleton connection manager with poolingMongoDBConversationRepository.ts- Repository implementationConversationDocumentMapper.ts- Entity-to-document mapper- Updated
DependencyContainer.ts- Async initialization + repository selection
Frontend (app/features/conversation/):
- New conversation sidebar component (shadcn/ui
Sidebar) - Conversation list with 50-100 items, sorted by recent activity
- Enhanced
useConversationhook withloadConversation()method - React Query integration for list fetching, optimistic updates, cache invalidation
API Endpoints:
GET /api/conversations/list?status=active&limit=100- List conversationsDELETE /api/conversations/:id- Hard delete conversationGET /api/health- MongoDB connection health check (Phase 2)
Technical Decisions Already Made
All architectural decisions have been documented by specialized agents:
Backend (.claude/doc/chat_history/backend.md):
- Connection pooling: MaxPoolSize=10, 60s idle timeout
- Document schema: Embedded messages (not referenced)
- Indexes:
{ _id: 1 },{ updatedAt: -1 },{ status: 1, updatedAt: -1 } - Error handling: Graceful fallback to InMemory on MongoDB failure
- Pagination: Skip + limit (100 default)
Frontend (.claude/doc/chat_history/frontend-data-architecture.md):
- State management: Keep existing
useConversationStorage(sessionStorage) - Caching: React Query with hierarchical query keys
- Optimistic updates: Delete mutations with rollback on error
- No URL params syncing (initially), no Suspense (traditional loading states)
UI/UX (.claude/doc/chat_history/sidebar-ui-design.md):
- Component: shadcn/ui v4
Sidebar(collapsible, responsive, accessible) - Layout: 280px desktop, full overlay mobile, hamburger menu toggle
- Actions: New Chat (default button), Delete (ghost + confirmation dialog)
- States: Loading (skeleton), empty, error, active highlighting
Definition of Done
Implementation Complete:
-
MongoDBClientsingleton with connection pooling and retry logic -
MongoDBConversationRepositoryimplementingIConversationRepositoryinterface -
ConversationDocumentMapperwith entity restoration viaConversation.restore() - Updated
DependencyContainerwith async initialization andREPOSITORY_TYPEenv variable -
GET /api/conversations/listendpoint with status filtering and pagination -
DELETE /api/conversations/:idendpoint for hard delete - Conversation sidebar component with shadcn/ui
Sidebar,ScrollArea,AlertDialog - Conversation list with title, preview, timestamp, delete button, active state
- Enhanced
useConversationhook withloadConversation(conversationId)method - React Query hooks:
useConversationsListQuery,useDeleteConversationMutation - Responsive behavior: Overlay on mobile (<768px), collapsible on desktop
- Empty state, loading state, error state with retry button
- Filter by status: All, Active, Archived with localStorage persistence
Edge Cases Handled:
- MongoDB connection failure → Fallback to InMemory + warning log
- Very long conversation titles → Truncate to 50 chars + "..." with tooltip
- Rapid conversation switching → Cancel pending requests, load last clicked
- Empty message content → Validation error
- Conversation at 1,000 message limit → Domain error with user prompt
Unit Tests Added (>80% coverage):
- Backend unit tests:
-
MongoConversationRepository.unit.test.ts(mocked MongoDB client) -
ConversationDocumentMapper.test.ts(round-trip entity → document → entity) -
ManageConversationUseCase.test.ts(mocked repository)
-
- Frontend unit tests:
-
useConversationsListQuery.test.tsx(fetch, error, caching, stale time) -
useDeleteConversationMutation.test.tsx(optimistic updates, rollback) -
Sidebar.test.tsx(rendering, collapse, filters, states, accessibility) -
ConversationListItem.test.tsx(click, delete, active state, truncation)
-
Integration Tests:
-
MongoConversationRepository.integration.test.ts(mongodb-memory-server)- Full CRUD lifecycle, pagination, filtering, concurrent operations
- Frontend integration tests:
-
conversation-switching.test.tsx(sidebar → chat flow) -
delete-conversation.test.tsx(delete → refetch → UI update) -
filter-conversations.test.tsx(filter changes → query updates)
-
Documentation Updated:
-
.env.examplewithMONGODB_URL,DATABASE_NAME,REPOSITORY_TYPEvariables - README.md with MongoDB setup instructions
- Architecture documentation in
.claude/doc/chat_history/(already created)
Code Review Approved:
- Hexagonal architecture compliance verified (no domain dependencies on infrastructure)
- Repository pattern correctly implemented
- Dependency injection via container
- Error handling with graceful degradation
CI/CD Passes:
- All unit tests pass (Vitest)
- All integration tests pass (mongodb-memory-server)
- ESLint passes
- TypeScript compilation succeeds
- Build succeeds (
yarn build)
Manual Testing Complete:
- Create new conversation → First message sent → Conversation appears in sidebar
- Click conversation in sidebar → Messages load → Active state highlighted
- Click "New Chat" → Current conversation cleared → Input focused
- Delete conversation → Confirmation dialog → Hard delete → Refetch list
- Filter by status → Active/Archived conversations shown correctly
- Responsive: Mobile overlay with backdrop, desktop collapsible sidebar
- Error handling: MongoDB down → Fallback to InMemory → Warning displayed
- Performance: Sidebar loads <2s with 50 conversations
Manual Testing Checklist
Basic Flow (5 minutes):
- Open app in fresh browser tab
- Send first message: "What is the weather in San Francisco?"
- Verify conversation appears in sidebar with title "What is the weather in San Francisco?"
- Send second message: "And what about New York?"
- Refresh page → Verify conversation persists and messages reload
- Click "New Chat" button → Verify chat clears and input is focused
- Send message in new conversation → Verify second conversation appears in sidebar
- Click first conversation → Verify messages load correctly
- Click delete button on second conversation → Confirm deletion → Verify removed from list
Edge Case Testing (3 minutes):
- Send message with 500+ characters → Verify title truncates to 50 chars + "..."
- Hover over truncated title → Verify tooltip shows full title
- Rapidly click between 3 conversations → Verify last clicked loads without errors
- Try to send empty message (whitespace only) → Verify validation error
Error Handling (3 minutes):
- Disconnect internet → Try to load sidebar → Verify error state with retry button
- Click retry → Verify loading state → Reconnect internet → Verify list loads
- Kill MongoDB (set invalid
MONGODB_URL) → Refresh app → Verify fallback to InMemory + console warning
Integration (2 minutes):
- Open app in two browser tabs with same conversation
- Send message in tab 1 → Switch to tab 2 → Refresh → Verify message appears
- Delete conversation in tab 1 → Switch to tab 2 → Refresh → Verify conversation gone
Responsive Behavior (2 minutes):
- Desktop (1920px): Verify sidebar is 280px wide, collapsible with hamburger icon
- Resize to tablet (768px): Verify sidebar pushes content, 320px wide
- Resize to mobile (375px): Verify sidebar is full overlay with backdrop
- Click conversation on mobile → Verify sidebar auto-closes after selection
- Test keyboard shortcut (Cmd/Ctrl+B) → Verify sidebar toggles
Acceptance Criteria Reference
Critical Path (Must Pass):
- AC-8.1.1: Zero message loss - All sent messages persisted successfully
- AC-8.2.1, AC-8.2.2: No duplicate conversations (UUID uniqueness)
- AC-8.3.1, AC-8.3.2: Correct message ordering (server timestamps)
- AC-6.1.1, AC-6.1.2: Load time <2s for list, <1.5s for conversation
- AC-4.2.2, AC-4.2.3: Hard delete with confirmation dialog
- AC-5.1.1, AC-5.1.3: MongoDB connection resilience (fallback to InMemory)
Important (Should Pass):
- AC-6.2.1: Sidebar 60fps animations (300ms transition)
- AC-NFR-1, AC-NFR-2, AC-NFR-3: WCAG 2.1 AA accessibility compliance
- AC-5.1.3: Error auto-recovery 90% success rate
- AC-7.1.1, AC-7.2.1, AC-7.3.1: Responsive design across 3 breakpoints
Complete acceptance criteria: .claude/doc/chat_history/acceptance-criteria.md (75+ criteria)
Implementation Plan
Phase 1: Backend Infrastructure (Priority: HIGH):
- Install
mongodbdriver:yarn add mongodb - Install test dependencies:
yarn add -D mongodb-memory-server - Create
MongoDBClientsingleton with connection pooling - Create
ConversationDocumentMapperwith entity restoration - Implement
MongoDBConversationRepository - Update
DependencyContainerfor async initialization - Add
GET /api/conversations/listendpoint - Add
DELETE /api/conversations/:idendpoint - Write unit tests (mocked MongoDB)
- Write integration tests (mongodb-memory-server)
Phase 2: Frontend Data Layer (Priority: HIGH):
- Install MSW for testing:
yarn add -D msw@latest - Create conversation list schema (Zod)
- Enhance
ConversationServicewithlistConversations()and error handling - Create
useConversationsListQueryhook - Enhance
useDeleteConversationMutationwith optimistic updates - Enhance
useConversationhook withloadConversation()method - Create
useSwitchConversationbusiness hook - Write unit tests for hooks and service
Phase 3: UI Components (Priority: HIGH):
- Install shadcn sidebar:
npx shadcn-ui@latest add sidebar - Create
ConversationSidebarcomponent (basic structure) - Create
ConversationListItemcomponent (title, preview, timestamp, delete) - Create
ConversationListcomponent (ScrollArea + list mapping) - Add empty state, loading state (skeleton), error state
- Add filter buttons (All, Active, Archived)
- Integrate sidebar in
layout.tsxwithSidebarProvider - Add
SidebarTriggerto Navbar - Write component tests (React Testing Library)
Phase 4: Integration & Polish (Priority: MEDIUM):
- Test full user flows (create, load, delete, filter)
- Test responsive behavior on 3 viewports
- Test error scenarios (MongoDB down, network errors)
- Verify accessibility (keyboard navigation, screen reader)
- Performance testing (50+ conversations)
- Write integration tests
- Update documentation (README, .env.example)
Phase 5: Monitoring & Optimization (Priority: LOW - Future):
- Add
/api/healthendpoint for MongoDB connection health - Implement query performance monitoring
- Add structured logging (pino/winston)
- Cursor-based pagination for >100 conversations
- Real-time updates via WebSocket (multi-device sync)
Dependencies
Environment Variables Required:
MONGODB_URL=mongodb+srv://user:pass@cluster.mongodb.net/
DATABASE_NAME=ai_chat_app
REPOSITORY_TYPE=mongodb # or 'inmemory' for testingNew Packages:
mongodb- MongoDB Node.js drivermongodb-memory-server(dev) - In-memory MongoDB for integration testsmsw(dev) - Mock Service Worker for frontend testing
Existing Dependencies (Already Installed):
@tanstack/react-query- State managementaxios- HTTP clientvitest- Test runner@testing-library/react- Component testingshadcn/ui- UI components
Related Documentation
All planning documents are in .claude/doc/chat_history/:
backend.md- MongoDB repository architecture (8,000+ words)frontend-data-architecture.md- React Query integration (6,000+ words)sidebar-ui-design.md- UI/UX specifications (5,000+ words)backend-testing-strategy.md- Testing approach (4,000+ words)frontend-testing-strategy.md- Frontend testing (4,500+ words)acceptance-criteria.md- 75+ acceptance criteria (11,500+ words)validation-checklist.md- Manual testing guide (quick reference)test-scenario-mapping.md- 135 test scenarios mapped to ACs
Session context: .claude/sessions/context_session_chat_history.md
Notes
- Architecture compliance: This feature strictly follows hexagonal architecture principles (zero domain dependencies on infrastructure)
- Incremental rollout: Use
REPOSITORY_TYPE=inmemoryfor local development,REPOSITORY_TYPE=mongodbfor production - Testing strategy: Dual approach - mocked unit tests + mongodb-memory-server integration tests
- MongoDB setup: MongoDB Atlas already configured at
mongodb+srv://connection:***@gurusup-prod.kyw62.mongodb.net - No migration needed: Fresh start - no data to migrate from InMemory