6.6 KiB
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
cd client
npm install
# or
pnpm install
Run Development Server
npm run dev
# Opens at http://localhost:3000
Build for Production
npm run build
# Output in dist/
Type Checking
npm run type-check
Linting
npm run lint
Design System - Monokai Dark Theme
The UI uses a Monokai-inspired color palette defined in 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 Codefor code/monospace elements
WebSocket Integration
The client maintains a persistent WebSocket connection to the server for control plane events.
Connection flow:
- Authenticate with JWT (obtained from login)
- Send
system.hellowith peer type and version - Receive
system.welcomewith assignedpeer_id - Join room with
room.join - Listen for events and send messages
See protocol_events_v_2.md for complete event protocol.
Key events to handle:
system.welcome- Store peer_idroom.joined- Update participant listchat.message.created- Display messagertc.offer/answer/ice- WebRTC signalingpresence.update- Update participant status
WebRTC Implementation
Call flow:
- Request capability token from server (via REST API)
- Create local media stream (
getUserMedia) - Create peer connection with ICE servers
- Send
rtc.offerwith capability token - Receive
rtc.answer - Exchange ICE candidates via
rtc.ice - Connection established, media flows P2P
Screen sharing:
- Use
getDisplayMediainstead ofgetUserMedia - 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:
// authStore.ts
{
user: User | null,
token: string | null,
peerId: string | null,
login: (username, password) => Promise<void>,
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<peerId, MediaStream>,
startCall: (peerId, type) => Promise<void>,
endCall: () => void
}
Component Guidelines
- Functional components with TypeScript
- Use hooks for side effects and state
- CSS Modules for component-scoped styles
- Semantic HTML
- Accessibility: ARIA labels, keyboard navigation
- 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
- Unit tests: Components, hooks, utilities
- Integration tests: WebSocket flows, WebRTC signaling
- 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.