React Frontend Analysis & iMessage-like UX Improvement Plan
Date: 2025-11-30 Status: Phase A - Investigation Complete Priority: High - Core User Experience Enhancement
Executive Summary
The React frontend (/home/ubuntu/workplace/AhaiaApp/ide/web-react/) is a modern, mobile-first chat application built with React 19, TypeScript, Vite, Socket.IO, and Tailwind CSS. It provides an iMessage-like interface for interacting with git repositories via command execution.
Key Finding: The frontend currently uses the OLD WebSocket API and lacks critical features to achieve a true iMessage-like experience. Users cannot reconnect to running jobs, see job history, or work across multiple repositories while jobs run in the background.
The new Phase 1 backend API provides all the capabilities needed (job persistence, reconnection, history), but the frontend does not yet leverage any of these features.
Current Architecture
Technology Stack
Frontend Framework: React 19.2.0 + TypeScript 5.9.3
Build Tool: Vite 7.2.4
Routing: React Router v7.9.6
WebSocket: Socket.IO Client 4.8.1
Styling: Tailwind CSS 3.4.18
UI Components: Custom components with Lucide icons
State Management: React Context API
Storage: localStorage for message history & agent preferences
Testing: Vitest + Playwright E2E
Application Structure
/home/ubuntu/workplace/AhaiaApp/ide/web-react/
├── src/
│ ├── App.tsx # Main app with routing
│ ├── main.tsx # Entry point
│ ├── contexts/ # Context providers
│ │ ├── ChatContext.tsx # WebSocket + message state (NEEDS UPDATE)
│ │ ├── RepositoryContext.tsx # Repository list fetching
│ │ ├── AgentContext.tsx # Agent registration & selection
│ │ └── DocsContext.tsx # Documentation library
│ ├── pages/ # Route pages
│ │ ├── ContactsPage.tsx # Repository list (chat list)
│ │ ├── ChatPage.tsx # Main chat interface
│ │ ├── DocsPage.tsx # Documentation library
│ │ └── DocViewPage.tsx # Individual doc viewer
│ ├── components/ # Reusable components
│ │ ├── JobMessage.tsx # Job output UI (NEEDS UPDATE)
│ │ ├── UserMessage.tsx # User message bubble
│ │ ├── SystemMessage.tsx # System notifications
│ │ ├── SwipeableMessage.tsx # Double-tap to delete messages
│ │ ├── AgentSelector.tsx # Mode/agent picker
│ │ └── ...
│ └── types/ # TypeScript types (NEEDS UPDATE)
│ └── index.ts
├── package.json
├── vite.config.ts
└── tailwind.config.js
Routes
/ -> ContactsPage (repository list)
/chat/:repoId -> ChatPage (chat with specific repo)
/docs -> DocsPage (documentation library)
/docs/:docId -> DocViewPage (view specific doc)
Current Features & UX Flow
What Works Well
1. iMessage-like Visual Design
- Clean, modern chat bubbles
- User messages on right (blue), system/job on left (gray)
- Smooth animations and transitions
- Mobile-first responsive design
- Dark mode support via
useDarkModehook
2. Message Persistence (localStorage)
- Messages stored per repository in
Map<repoId, Message[]> - Persisted to localStorage with debouncing (500ms)
- Survives page refresh
- Storage key:
'chat-message-history'
3. Multi-Repository Support
- Repository list on Contacts page
- Switch between repos via routing (
/chat/:repoId) - Each repo maintains separate message history
4. Dual Execution Modes
- Shell mode: Direct bash commands
- Agent mode: Registered AI agents (e.g., claude-code)
- Agent selection UI with visual icons
- Last used agent remembered per repo
5. Job UI States
- Simple message (<1s): Compact bubble with output
- Job UI (>1s): Full card with header, output, footer
- Running jobs show spinner, cancel button, cursor animation
- Completed jobs show status footer (✓/❌) with exit code and duration
- Auto-scrolling output during execution
6. Message Management
- Double-tap (mobile) or double-click (desktop) to reveal delete button
- Swipe animation slides message to reveal red delete action
- Different swipe directions for user (left) vs job messages (right)
7. Real-time Output Streaming
- WebSocket connection via Socket.IO
- Live stdout/stderr streaming
- Output appends to message as it arrives
- Auto-scroll to bottom for running jobs
Current Limitations (Blocking iMessage-like UX)
CRITICAL GAPS - What Prevents iMessage Feel
1. No Job Reconnection After Disconnect
Problem:
// ChatContext.tsx lines 147-169
socket.on('job-started', (data: JobStartedEvent) => {
console.log('Job started:', data.jobId)
})
socket.on('output', (data: OutputEvent) => {
updateJobOutput(data.jobId, data.data)
})
socket.on('job-complete', (data: JobCompleteEvent) => {
completeJob(data.jobId, data.exitCode, data.duration)
})
- Only listens to real-time events for jobs started in current session
- No
list-jobsorsubscribe-jobusage (new Phase 1 API) - If user loses connection or switches repos, running jobs are lost from view
- On reconnect, no attempt to fetch running jobs or buffered output
Impact:
- User CANNOT switch repos while job runs
- Network hiccup = lost job visibility
- Page refresh = lost running jobs
- No way to resume watching a long-running build
User Story Broken:
"Start
npm installin Repo A, switch to Repo B to fix a bug, come back to see install results"Current behavior: Install output is lost when switching repos
2. No Job History Visible
Problem:
// ChatContext.tsx - Messages are stored, but no way to view past jobs
const [messagesByRepo, setMessagesByRepo] = useState<Map<string, Message[]>>(...)
- Messages ARE persisted to localStorage
- But there's no UI to browse job history
- No way to re-view completed job outputs
- No "recent jobs" sidebar or panel
- No job status indicators in repository list
Impact:
- Can't review what commands were run
- Can't check exit codes from earlier today
- No job timeline or audit trail visible
- Can't easily re-run previous commands
User Story Broken:
"Show me all the tests I ran today and which ones failed"
Current behavior: Must scroll through chat messages to find jobs
3. No Background Job Notifications
Problem:
// ChatContext.tsx - completeJob() only updates state
const completeJob = useCallback((jobId: string, exitCode: number, duration: number) => {
const repo = currentRepoRef.current
if (!repo) return // ⚠️ If user switched repos, completion is ignored
setMessagesByRepo((prev) => {
// Only updates messages for CURRENT repo
})
}, [])
- Job completion only updates if user is viewing that repo
- No notification when job finishes in background repo
- No badge/counter on ContactsPage showing running jobs
- No toast/alert when build completes while user is elsewhere
Impact:
- Must stay on chat page to see job completion
- No awareness of background activity
- Can't multitask effectively
- Breaks async, multi-context workflow
User Story Broken:
"Run tests in Repo A, work in Repo B, get notified when tests finish"
Current behavior: No notification, must manually check back
4. No Visual Indicators for Running Jobs
Problem:
- ContactsPage shows last commit message and branch
- But NO indicator if job is currently running in that repo
- No spinner badge, no "Running..." text
- User has no idea which repos have active jobs
Impact:
- Can't see at a glance where work is happening
- Must open each repo to check job status
- No dashboard view of active jobs
User Story Broken:
"See which repos have running jobs from the repo list"
Current behavior: No visual indicator
5. Output Lost on Disconnect
Problem:
// ChatContext.tsx lines 151-154
socket.on('output', (data: OutputEvent) => {
console.log('Output received:', data.jobId, data.data)
updateJobOutput(data.jobId, data.data) // Only appends if connected
})
- Output only received if socket is connected
- If connection drops for 10 seconds during a build, that output is GONE
- No use of
get-job-outputto fetch buffered output - No reconnection logic to catch up on missed output
Impact:
- Network glitches cause permanent output loss
- Can't review what happened during disconnect
- Debugging failed jobs becomes impossible if disconnected during failure
User Story Broken:
"WiFi dropped for 30 seconds during build - what errors occurred?"
Current behavior: Output from those 30 seconds is lost forever
6. No Job Persistence Across Page Refresh
Problem:
- Messages are persisted to localStorage ✓
- But running job PROCESSES are not tracked
- On page refresh, job message shows as "RUNNING" forever
- No reconnection to actual process
- Job never completes in UI
Impact:
- Page refresh during job = stuck UI
- Job message shows spinning forever
- No way to recover or see actual job status
User Story Broken:
"Accidentally refresh page during long test run"
Current behavior: Test continues on server, but UI shows frozen "Running..." forever
MEDIUM PRIORITY GAPS
7. No Global Job Dashboard
- Can't see all running jobs across all repos in one view
- No centralized place to cancel old jobs
- No resource monitoring or limits visible
8. No Job Filtering/Search
- Can't filter messages to show only jobs
- Can't search job history by command
- No grouping by status (running/completed/failed)
9. No Job Metadata
- Jobs don't show start time in history
- No duration visible until completion
- No tagging or categorization
10. Websocket Reconnection UX
// ChatContext.tsx lines 141-145
socket.on('disconnect', () => {
console.log('Socket disconnected')
setIsConnected(false)
})
- Shows "Disconnected - Reconnecting..." banner
- But no automatic job re-subscription on reconnect
- User must manually re-execute or switch repos to trigger update
Current WebSocket API Usage
Events Currently Used (Old API)
// OUTGOING (Client → Server)
socket.emit('execute', {
repoPath: string,
mode: 'shell' | 'agent',
command?: string, // shell mode
agentCommand?: string, // agent mode
userInput?: string, // agent mode
jobId: string // client-generated
})
socket.emit('cancel', { jobId: string })
// INCOMING (Server → Client)
socket.on('job-started', ({ jobId }) => {...})
socket.on('output', ({ jobId, data, stream }) => {...})
socket.on('job-complete', ({ jobId, exitCode, duration }) => {...})
socket.on('job-cancelled', ({ jobId }) => {...})
socket.on('job-error', ({ jobId, error }) => {...})
Events NOT Used (New Phase 1 API)
// ❌ NOT IMPLEMENTED - Need to add these
// List jobs for reconnection
socket.emit('list-jobs', { repoId, status: 'running', limit: 50 })
socket.on('jobs-list', ({ jobs }) => {...})
// Subscribe to running/completed job
socket.emit('subscribe-job', { jobId })
socket.on('job-subscribed', ({ jobId, status, jobDetails }) => {...})
// Get buffered output
socket.emit('get-job-output', { jobId, fromSequence: 0, limit: 1000 })
socket.on('job-output', ({ jobId, outputs }) => {...})
// Unsubscribe when leaving
socket.emit('unsubscribe-job', { jobId })
socket.on('job-unsubscribed', ({ jobId }) => {...})
Code Locations Needing Changes
1. ChatContext.tsx
Location: /home/ubuntu/workplace/AhaiaApp/ide/web-react/src/contexts/ChatContext.tsx
Changes Needed:
- Add
useEffectto fetch running jobs on mount/reconnect (lines ~175) - Implement
list-jobsemission when repository changes - Implement
subscribe-jobfor each running job found - Implement
get-job-outputto fetch buffered output - Add reconnection logic on
connectevent - Handle
jobs-list,job-subscribed,job-outputevents - Track active subscriptions to avoid duplicate subscriptions
- Unsubscribe from jobs when switching repos
Complexity: Medium-High (60-100 lines of new code)
2. JobMessage.tsx
Location: /home/ubuntu/workplace/AhaiaApp/ide/web-react/src/components/JobMessage.tsx
Changes Needed:
- Add visual indicator for "reconnected" jobs
- Show buffered output badge ("catching up on 500 lines...")
- Add "View in History" button for completed jobs
- Optionally add progress indicator for known-duration jobs
Complexity: Low (20-30 lines)
3. ChatPage.tsx
Location: /home/ubuntu/workplace/AhaiaApp/ide/web-react/src/pages/ChatPage.tsx
Changes Needed:
- Add job history panel (sidebar or bottom drawer)
- Add filter buttons (All/Running/Completed/Failed)
- Subscribe to running jobs when entering repo
- Show loading state while fetching job list
Complexity: Medium (100-150 lines for new job history component)
4. ContactsPage.tsx
Location: /home/ubuntu/workplace/AhaiaApp/ide/web-react/src/pages/ContactsPage.tsx
Changes Needed:
- Add badge showing count of running jobs per repo
- Add spinner icon overlay if jobs are running
- Fetch running job counts via API or WebSocket
- Optionally add background job completion notifications
Complexity: Low-Medium (30-50 lines)
5. types/index.ts
Location: /home/ubuntu/workplace/AhaiaApp/ide/web-react/src/types/index.ts
Changes Needed:
- Add interfaces for new WebSocket events:
export interface ListJobsRequest { repoId: string; status?: string; limit?: number } export interface JobsListEvent { jobs: JobData[] } export interface SubscribeJobRequest { jobId: string } export interface JobSubscribedEvent { jobId: string; status: string; jobDetails: JobData } export interface GetJobOutputRequest { jobId: string; fromSequence?: number; limit?: number } export interface JobOutputEvent { jobId: string; outputs: OutputChunk[] } export interface JobData { id: string repo_id: string command: string mode: 'shell' | 'agent' status: 'running' | 'completed' | 'failed' | 'cancelled' exit_code: number | null started_at: string completed_at: string | null created_by: string repo_name: string repo_path: string } export interface OutputChunk { sequence: number stream: 'stdout' | 'stderr' data: string timestamp: string }
Complexity: Low (30-40 lines)
6. New Component: JobHistoryPanel.tsx
Location: /home/ubuntu/workplace/AhaiaApp/ide/web-react/src/components/JobHistoryPanel.tsx (NEW FILE)
Features:
- Collapsible sidebar or bottom drawer
- List of recent jobs for current repo
- Filter by status (running/completed/failed)
- Click job to scroll to it in chat or view full output
- Visual states: spinner for running, ✓ for completed, ✗ for failed
- Timestamp and duration for each job
- "Load More" pagination
Complexity: Medium (150-200 lines)
7. New Component: JobNotification.tsx
Location: /home/ubuntu/workplace/AhaiaApp/ide/web-react/src/components/JobNotification.tsx (NEW FILE)
Features:
- Toast notification when job completes in background repo
- Shows job command, exit status, duration
- Click to navigate to that repo
- Auto-dismiss after 5 seconds
- Queue multiple notifications
Complexity: Low-Medium (80-100 lines)
8. New Hook: useJobReconnection.ts
Location: /home/ubuntu/workplace/AhaiaApp/ide/web-react/src/hooks/useJobReconnection.ts (NEW FILE)
Features:
- Encapsulate reconnection logic
- Fetch running jobs on mount
- Subscribe to each running job
- Fetch buffered output
- Unsubscribe on unmount
- Handle errors gracefully
Complexity: Medium (100-120 lines)
Improvement Plan - Detailed Design
Phase B Implementation Roadmap
Priority 1: Job Reconnection (Critical)
Goal: Users can reconnect to running jobs after disconnect/navigation
Tasks:
- Update TypeScript types with new Phase 1 event interfaces
- Add
list-jobsemission on repository mount in ChatContext - Subscribe to all running jobs found
- Fetch buffered output via
get-job-output - Handle
job-subscribedevent to receive buffered + new output - Unsubscribe from jobs when switching repos
- Add visual indicator in JobMessage for reconnected jobs
Acceptance Criteria:
- User starts job, refreshes page, sees job still running with all output
- User starts job, switches repo, returns, sees job completion
- Lost output during disconnect is recovered on reconnect
- No duplicate subscriptions or memory leaks
Files to Modify:
src/types/index.tssrc/contexts/ChatContext.tsxsrc/components/JobMessage.tsx
Estimated Effort: 3-4 hours
Priority 2: Job History UI (Important)
Goal: Users can browse past jobs and re-view outputs
Tasks:
- Create
JobHistoryPanel.tsxcomponent - Add toggle button in ChatPage header
- Fetch job list via
list-jobs(no status filter = all jobs) - Display jobs with status icons, timestamps, durations
- Click job to scroll to it or expand full output
- Add filter buttons (All/Running/Completed/Failed)
- Implement pagination for large job lists
Acceptance Criteria:
- Panel slides in from right or bottom
- Shows last 20 jobs by default
- Running jobs show spinner
- Completed jobs show ✓ with exit code
- Failed jobs show ✗ with exit code
- Click job navigates to it in chat or opens modal
Files to Create:
src/components/JobHistoryPanel.tsx
Files to Modify:
src/pages/ChatPage.tsxsrc/contexts/ChatContext.tsx(add job fetching method)
Estimated Effort: 4-5 hours
Priority 3: Background Job Notifications (Important)
Goal: Users get notified when jobs complete in background repos
Tasks:
- Create
JobNotification.tsxtoast component - Track active repository in global state
- When job completes, check if user is viewing different repo
- Show toast notification with job details
- Click toast to navigate to that repo
- Support multiple notifications in queue
- Add dismiss/auto-dismiss logic
Acceptance Criteria:
- Job completes in Repo A while user is in Repo B
- Toast appears: "Build completed in Repo A (exit 0, 2m 15s)"
- Click toast navigates to Repo A
- Multiple toasts stack vertically
- Toast auto-dismisses after 5 seconds
Files to Create:
src/components/JobNotification.tsx
Files to Modify:
src/contexts/ChatContext.tsx(add notification logic)src/App.tsx(add notification container)
Estimated Effort: 3-4 hours
Priority 4: Running Job Indicators (Polish)
Goal: Show which repos have running jobs in repository list
Tasks:
- Fetch running job counts for all repos
- Add badge overlay on repository avatars
- Add spinner icon if jobs running
- Update badge count in real-time as jobs complete
- Optionally cache counts in localStorage for faster initial load
Acceptance Criteria:
- ContactsPage shows badge "2" on repo with 2 running jobs
- Badge updates in real-time when job completes
- Spinner icon visible on repos with active jobs
- Click repo navigates to chat showing running jobs
Files to Modify:
src/pages/ContactsPage.tsxsrc/contexts/ChatContext.tsx(add global job tracking)
Estimated Effort: 2-3 hours
Priority 5: Graceful Reconnection UX (Polish)
Goal: Seamless reconnection experience
Tasks:
- Show reconnecting modal/banner during disconnect
- On reconnect, re-subscribe to active jobs
- Fetch missed output
- Show "Syncing..." badge while catching up
- Animate output appearing (scroll smoothly)
- Handle edge case: job completed during disconnect
Acceptance Criteria:
- Network drops, user sees "Reconnecting..." banner
- Network returns, banner shows "Syncing jobs..."
- Missed output appears smoothly
- No jarring UI jumps or errors
Files to Modify:
src/contexts/ChatContext.tsxsrc/components/JobMessage.tsxsrc/pages/ChatPage.tsx(reconnection UI)
Estimated Effort: 2-3 hours
Priority 6: Mobile Optimizations (Nice-to-Have)
Goal: Perfect mobile experience
Tasks:
- Add pull-to-refresh on ContactsPage
- Optimize job history panel for small screens (bottom drawer)
- Add haptic feedback on job completion (if supported)
- Test and optimize touch targets (min 44px)
- Ensure notifications don't block input
- Add swipe gesture to close job history panel
Acceptance Criteria:
- Pull down on contacts refreshes repo list
- Job history opens as bottom sheet on mobile
- Notifications appear at top, don't block send button
- All buttons easily tappable on phone
Files to Modify:
src/pages/ContactsPage.tsxsrc/components/JobHistoryPanel.tsxsrc/components/JobNotification.tsx
Estimated Effort: 3-4 hours
Implementation Strategy
Step-by-Step Execution Plan
STEP 1: Update Type Definitions (30 min)
- Open
src/types/index.ts - Add new event interfaces (ListJobsRequest, JobsListEvent, etc.)
- Add JobData and OutputChunk interfaces
- Update ChatContextValue with new methods if needed
STEP 2: Implement Job Reconnection in ChatContext (2-3 hours)
- Add state for tracking active subscriptions
- Add
fetchRunningJobs()method that emitslist-jobs - Add
subscribeToJob(jobId)method that emitssubscribe-job - Add
unsubscribeFromJob(jobId)method - Add event handlers for
jobs-list,job-subscribed,job-output - Call
fetchRunningJobs()when repository changes - Call
fetchRunningJobs()on socket reconnect - Unsubscribe from old jobs when switching repos
STEP 3: Update JobMessage Component (30 min)
- Add prop for
isReconnectedboolean - Show badge "Reconnected" if applicable
- Test with reconnected jobs
STEP 4: Test Reconnection (1 hour)
- Start long job (sleep 60)
- Refresh page → verify job still visible
- Switch repos → verify job continues
- Return to repo → verify job completion
- Disconnect WiFi → verify reconnection works
STEP 5: Create Job History Panel (3-4 hours)
- Create new component file
- Implement collapsible panel UI (drawer)
- Fetch jobs via ChatContext
- Display job list with icons/timestamps
- Implement filters (All/Running/Completed/Failed)
- Add click handler to scroll to job in chat
- Integrate into ChatPage
STEP 6: Test Job History (30 min)
- Run several jobs
- Open history panel
- Verify all jobs listed
- Test filters
- Test clicking jobs
STEP 7: Implement Background Notifications (2-3 hours)
- Create toast component
- Add global notification state
- Detect when job completes in background repo
- Show toast with details
- Implement click-to-navigate
- Test queue and auto-dismiss
STEP 8: Test Notifications (30 min)
- Run job in Repo A
- Switch to Repo B
- Wait for job completion
- Verify toast appears
- Click toast → verify navigation
STEP 9: Add Running Job Indicators (2 hours)
- Track running jobs globally
- Add badge to ContactsPage repo items
- Update counts in real-time
- Style spinner overlay
STEP 10: Polish & Mobile Testing (2-3 hours)
- Test all features on mobile device
- Fix touch target issues
- Optimize animations
- Add pull-to-refresh
- Test edge cases (rapid switching, multiple jobs, etc.)
Testing Checklist
Reconnection Tests
- Start job → refresh page → job still running
- Start job → close tab → reopen → job visible
- Start job → disconnect WiFi → reconnect → output recovered
- Start job → switch repos → return → job completed
- Multiple running jobs → all reconnect properly
- Completed job → refresh → can view output
Job History Tests
- History panel shows recent jobs
- Filters work (All/Running/Completed/Failed)
- Click job scrolls to message
- Pagination loads older jobs
- Panel closes when switching repos
Notification Tests
- Job completes in background → toast appears
- Multiple jobs complete → toasts queue
- Click toast → navigates to repo
- Toast auto-dismisses after 5s
- Dismiss button works
Running Job Indicators
- Badge shows correct count on ContactsPage
- Badge updates when job completes
- Spinner visible on active repos
- No badge on repos with no running jobs
Edge Cases
- Job completes during disconnect → correct state on reconnect
- Rapid repo switching → no subscription leaks
- Very long output (>10MB) → handles gracefully
- Cancel job → updates all UIs correctly
- Server restart → graceful reconnection
Backward Compatibility
Ensuring Old Backend Compatibility
The frontend should detect if the backend supports Phase 1 features:
// Feature detection
const hasPhase1Support = useRef(false)
useEffect(() => {
// Try to list jobs - if it fails, backend doesn't support it
socket.emit('list-jobs', { repoId: 'test' })
const timeout = setTimeout(() => {
hasPhase1Support.current = false
}, 1000)
socket.once('jobs-list', () => {
hasPhase1Support.current = true
clearTimeout(timeout)
})
socket.once('jobs-list-error', () => {
hasPhase1Support.current = false
clearTimeout(timeout)
})
}, [])
If Phase 1 not supported, gracefully disable:
- Job reconnection
- Job history (only show messages in chat)
- Background notifications
Performance Considerations
State Management
- Use
useCallbackfor event handlers to prevent re-renders - Debounce localStorage writes (already implemented: 500ms)
- Limit job history to last 100 jobs (pagination for older)
WebSocket Efficiency
- Unsubscribe from jobs when leaving repo to reduce server load
- Batch
subscribe-jobcalls if reconnecting to many jobs - Use
fromSequenceparameter to avoid re-fetching output
Rendering Optimization
- Virtualize job history list if >50 jobs (react-window)
- Memo-ize JobMessage component to prevent re-renders
- Lazy load job outputs (only fetch when viewed)
Mobile PWA Considerations
Current PWA Setup
// package.json
"vite-plugin-pwa": "^1.1.0"
The app appears to be configured as a PWA. Future enhancements:
- Push notifications via service worker (Phase 2)
- Background sync for job status
- Offline mode with job queue
Visual Design Mock-ups
Job History Panel (Desktop)
┌─────────────────────────────────────────────────────┐
│ Repo: AhaiaApp [X] │
├─────────────────────────────────────────────────────┤
│ Filters: [All] [Running] [Completed] [Failed] │
├─────────────────────────────────────────────────────┤
│ Running (2) │
│ ⚙ npm test 5m ago [Cancel] │
│ ⚙ git clone ... 10m ago [Cancel] │
│ │
│ Recent (10) │
│ ✓ npm install 1h ago 32s exit 0 │
│ ✗ npm run build 2h ago 5m exit 1 │
│ ✓ git status 3h ago 1s exit 0 │
│ ... │
│ │
│ [Load More] │
└─────────────────────────────────────────────────────┘
Background Notification (Toast)
┌─────────────────────────────────────────────┐
│ ✓ Build completed in Repo A │
│ Exit code 0 · 2m 15s │
│ [View] [Dismiss] │
└─────────────────────────────────────────────┘
ContactsPage with Job Indicators
┌─────────────────────────────────────────────┐
│ [AH] AhaiaApp ⚙ 2 │
│ Running tests... │
│ main │
├─────────────────────────────────────────────┤
│ [MR] my-react-app │
│ Fix navbar styling │
│ feature/navbar │
└─────────────────────────────────────────────┘
Success Metrics
Before (Current State)
- Jobs lost on disconnect: 100%
- Output buffered for later viewing: 0%
- Job history visible: Only in chat messages
- Reconnection to running jobs: 0%
- Background job notifications: None
- Running job indicators: None
After (Target State)
- Jobs persist across sessions: 100%
- Output buffered: Complete (up to 10MB per job)
- Job history: Dedicated panel with filters
- Reconnection success: 100%
- Background notifications: Real-time toasts
- Running job indicators: Badge + spinner on ContactsPage
- User can switch repos while jobs run: Yes
- User sees missed output on reconnect: Yes
- iMessage-like feel achieved: Yes
Risk Assessment
Technical Risks
Risk 1: WebSocket Subscription Leaks
- Likelihood: Medium
- Impact: High (memory leaks, duplicate events)
- Mitigation: Careful subscription tracking, cleanup on unmount
Risk 2: Rapid Repo Switching
- Likelihood: Medium
- Impact: Medium (confused UI state)
- Mitigation: Cancel pending subscriptions, debounce repo changes
Risk 3: Large Output Handling
- Likelihood: Low
- Impact: Medium (UI slowdown)
- Mitigation: Virtualize output, limit shown lines, "View Full" button
Risk 4: Backward Compatibility
- Likelihood: Low (backend already deployed)
- Impact: High (breaks old deployments)
- Mitigation: Feature detection, graceful fallback
Dependencies to Install
No new dependencies required! All features can be built with existing stack:
- ✓ Socket.IO client (already installed)
- ✓ React Router (for navigation)
- ✓ Tailwind (for styling)
- ✓ Lucide icons (for UI elements)
Optional for performance:
react-window- for virtualizing long job lists (can add if needed)
Environment Variables
No new environment variables needed. Existing:
VITE_API_BASE_URL=http://localhost:3000 # Backend URL
Browser Compatibility
Target browsers:
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Mobile Safari (iOS 14+)
- Chrome Mobile (Android)
All Phase 1 features use standard APIs (WebSocket, localStorage, React).
Conclusion - Phase A Summary
Current State
The React frontend is a well-architected, mobile-first chat application with excellent visual design and UX polish. It uses modern React patterns (hooks, context, router) and has a solid foundation.
Critical Gap
The frontend does NOT leverage the new Phase 1 backend API. It still uses the old real-time-only WebSocket pattern without job persistence, reconnection, or history.
What This Means
Users experience the same limitations that prompted the Phase 1 backend work:
- Can't reconnect to running jobs
- Can't switch repos while jobs run
- Can't review job history
- No notifications for background jobs
- Lost output on disconnect
The Good News
All the backend capabilities needed are ALREADY IMPLEMENTED and working. The frontend just needs to:
- Call the new WebSocket events (
list-jobs,subscribe-job,get-job-output) - Add UI components for job history and notifications
- Handle reconnection logic
Effort Estimate
Total Implementation Time: 18-24 hours
- Priority 1 (Reconnection): 3-4 hours
- Priority 2 (Job History): 4-5 hours
- Priority 3 (Notifications): 3-4 hours
- Priority 4 (Indicators): 2-3 hours
- Priority 5 (Reconnection UX): 2-3 hours
- Priority 6 (Mobile): 3-4 hours
Recommendation
Proceed to Phase B. The implementation is straightforward, low-risk, and will dramatically improve the user experience to match the "iMessage for repos" vision.
Next Steps
User Decision Required:
Should I proceed with Phase B implementation?
If yes, I will:
- Start with Priority 1 (Job Reconnection) - the most critical feature
- Implement each priority sequentially with testing
- Provide progress updates after each major component
- Share screenshots/descriptions of new UI
- Create a testing checklist for you to validate
Estimated completion: Phase B can be completed in 1-2 days of focused work.
Document Status: Phase A Complete - Awaiting Phase B Authorization