# CLAUDE.md — Mesh Client This file provides client-specific guidance for the Mesh web application. ## Client Role The Mesh Client is a web application (React/TypeScript) that provides: - User interface for chat, audio/video calls, screen sharing - **WebRTC media plane**: Direct P2P audio/video/screen connections - WebSocket connection to server for control plane - Integration with desktop agent for advanced features **Critical**: The client handles WebRTC media directly (P2P). File/folder/terminal sharing is delegated to the desktop agent via QUIC. ## Technology Stack - **React 18** with TypeScript - **Vite** for build tooling - **React Router** for navigation - **TanStack Query** for server state management - **Zustand** for client state management - **simple-peer** for WebRTC abstraction - **Monokai-inspired dark theme** ## Project Structure ``` client/ ├── src/ │ ├── main.tsx # App entry point │ ├── App.tsx # Main app component │ ├── pages/ │ │ ├── Login.tsx # Login page │ │ └── Room.tsx # Main room interface │ ├── components/ │ │ ├── Chat/ # Chat components │ │ ├── Video/ # Video call components │ │ ├── Participants/ # Participant list │ │ └── Controls/ # Call controls │ ├── lib/ │ │ ├── websocket.ts # WebSocket client │ │ ├── webrtc.ts # WebRTC manager │ │ └── events.ts # Event handlers │ ├── stores/ │ │ ├── authStore.ts # Auth state │ │ ├── roomStore.ts # Room state │ │ └── callStore.ts # Call state │ ├── hooks/ │ │ ├── useWebSocket.ts # WebSocket hook │ │ └── useWebRTC.ts # WebRTC hook │ ├── types/ │ │ └── events.ts # Event type definitions │ └── styles/ │ ├── global.css # Global styles │ └── theme.css # Monokai theme ├── public/ ├── index.html ├── package.json ├── tsconfig.json ├── vite.config.ts └── CLAUDE.md ``` ## Development Commands ### Setup ```bash cd client npm install # or pnpm install ``` ### Run Development Server ```bash npm run dev # Opens at http://localhost:3000 ``` ### Build for Production ```bash npm run build # Output in dist/ ``` ### Type Checking ```bash npm run type-check ``` ### Linting ```bash npm run lint ``` ## Design System - Monokai Dark Theme The UI uses a Monokai-inspired color palette defined in [src/styles/theme.css](src/styles/theme.css): **Colors**: - Background Primary: `#272822` - Background Secondary: `#1e1f1c` - Text Primary: `#f8f8f2` - Accent Primary (cyan): `#66d9ef` - Accent Success (green): `#a6e22e` - Accent Warning (orange): `#fd971f` - Accent Error (pink): `#f92672` **Typography**: - System font stack with fallbacks - `Fira Code` for code/monospace elements ## WebSocket Integration The client maintains a persistent WebSocket connection to the server for control plane events. **Connection flow**: 1. Authenticate with JWT (obtained from login) 2. Send `system.hello` with peer type and version 3. Receive `system.welcome` with assigned `peer_id` 4. Join room with `room.join` 5. Listen for events and send messages See [protocol_events_v_2.md](../protocol_events_v_2.md) for complete event protocol. **Key events to handle**: - `system.welcome` - Store peer_id - `room.joined` - Update participant list - `chat.message.created` - Display message - `rtc.offer/answer/ice` - WebRTC signaling - `presence.update` - Update participant status ## WebRTC Implementation **Call flow**: 1. Request capability token from server (via REST API) 2. Create local media stream (`getUserMedia`) 3. Create peer connection with ICE servers 4. Send `rtc.offer` with capability token 5. Receive `rtc.answer` 6. Exchange ICE candidates via `rtc.ice` 7. Connection established, media flows P2P **Screen sharing**: - Use `getDisplayMedia` instead of `getUserMedia` - Same signaling flow with screen capability token **Important**: - Always include capability token in WebRTC signaling messages - Handle ICE connection failures gracefully - Implement reconnection logic - Clean up media streams on disconnect ## State Management **Zustand stores**: ```typescript // authStore.ts { user: User | null, token: string | null, peerId: string | null, login: (username, password) => Promise, logout: () => void } // roomStore.ts { currentRoom: Room | null, participants: Participant[], messages: Message[], joinRoom: (roomId) => void, sendMessage: (content) => void } // callStore.ts { activeCall: Call | null, localStream: MediaStream | null, remoteStreams: Map, startCall: (peerId, type) => Promise, endCall: () => void } ``` ## Component Guidelines 1. **Functional components with TypeScript** 2. **Use hooks for side effects and state** 3. **CSS Modules for component-scoped styles** 4. **Semantic HTML** 5. **Accessibility**: ARIA labels, keyboard navigation 6. **Error boundaries** for graceful error handling ## Security Considerations - **Never store JWT in localStorage** (use httpOnly cookies or memory) - **Validate all incoming WebSocket messages** - **Sanitize user-generated content** (messages, usernames) - **Verify WebRTC fingerprints** (optional, V1+) - **No sensitive data in console logs** ## Performance Optimization - **Lazy load routes** with React.lazy - **Virtualize long lists** (messages, participants) - **Debounce input handlers** - **Memoize expensive computations** (useMemo) - **Avoid unnecessary re-renders** (React.memo) ## Testing Strategy 1. **Unit tests**: Components, hooks, utilities 2. **Integration tests**: WebSocket flows, WebRTC signaling 3. **E2E tests**: Complete user journeys (login, join room, send message, call) ## Browser Support - **Chrome/Edge**: 90+ - **Firefox**: 88+ - **Safari**: 15+ WebRTC requires modern browsers. Provide warning for unsupported browsers. ## Environment Variables Create `.env.local` for development: ``` VITE_API_URL=http://localhost:8000 VITE_WS_URL=ws://localhost:8000/ws ``` ## Build & Deployment The client builds to static files that can be served via: - Nginx/Caddy - CDN (CloudFront, Cloudflare) - Docker container with nginx **Important**: Configure CORS on the server to allow client origin. --- **Remember**: The client handles only WebRTC media (audio/video/screen) in P2P mode. File/folder/terminal sharing requires the desktop agent.