Walkie-Talkie

A real-time communication and messaging platform built with React and Vite. Supports cloud-based messaging via Appwrite and LAN peer-to-peer audio via WebRTC (PeerJS). Users join shared rooms using hashed passwords (cloud) or generated room codes (LAN), communicate via corkboard messages or push-to-talk audio, with no user accounts required.

Tech Stack

TechnologyVersionPurpose
React^19.2.3UI framework — functional components + hooks
Vite^7.3.1Build tool / dev server (migrated from CRA)
JavaScript (ES2022)ES ModulesPrimary language — no TypeScript
Appwrite SDK^21.5.0Backend — auth, database, storage
PeerJS^1.5.5WebRTC abstraction for LAN peer-to-peer audio
Web Audio APIBrowser built-inAudio recording and playback
Vitest^4.0.17Test framework with jsdom environment
ESLintFlat configLinting with React + React Hooks plugins
Vercel—Deployment

Key Decisions

DecisionRationaleOutcome
React + ViteModern build tooling, fast HMR, simpler than CRAGood — fast dev iteration
Migrate Firebase to AppwriteSimpler self-hosting, aligned with org infrastructure goalsGood — easier backend control
SHA-256 hashed password as corkboard IDPassword-derived ID without server-side authGood — simple shared access model
Appwrite anonymous authSession management without user accountsGood — frictionless entry
PeerJS + PeerServer for WebRTCAbstracts WebRTC connection complexity for LAN commsGood — simpler peer management
Predictable host peer ID formatroomCode-host enables joiners to find host directlyGood — no discovery server needed
Exclude confusing chars from room codesNo 0/O, 1/I/L for human readabilityGood — fewer user errors
crypto.getRandomValues for room codesSecure random generationGood — cryptographically safe
useRef for peer instance trackingAvoids stale closures in PeerJS event handlersGood — prevents callback bugs
3 simplified connection statesconnecting/connected/disconnected for clean UIGood — easy to reason about
navigator.onLine for connection detectionZero-dependency connection status using browser APIGood — lightweight, reliable
Answer calls without stream for receive-onlyEnables listening before microphone is enabledGood — flexible audio model
50 message limit per corkboardPrevents free-tier Appwrite storage abuseGood — explicit resource limits

Patterns Established

PatternDescriptionReusable
useConnectionStatus hookTracks browser online/offline via navigator.onLineYes
useNewMessageNotification hookDetects new incoming messages, excludes own messagesYes
usePeer hookManages PeerJS peer connection lifecycle and stateYes
useRoom hookRoom creation, joining, peer tracking via data channelsYes
useAudio hookWebRTC audio stream management with mic permissionsYes
appwriteService abstractionService layer wrapping Appwrite SDK operationsYes
MIME type fallback patternFallback chain for MediaRecorder (webm/mp4/ogg)Yes
Centralized constants fileAUDIO, STORAGE, SECURITY, UI, FEATURES constantsYes
ErrorBoundary componentReact error boundary with fallback UIYes
ErrorToast componentAuto-dismissing error notificationYes

Lessons Learned

LessonImpact
Safari/iOS needs mp4/x-m4a MIME fallbacks for MediaRecorderWebM not supported on all browsers — always implement fallback chain
useRef avoids stale closures in PeerJS event handlersState values were stale inside peer callbacks
Real-time Appwrite subscriptions need refetch patternSubscribe for notifications, then refetch full data
Retry connection with ref tracking prevents cleanup race conditionsReact cleanup could cancel in-progress connections
Input sanitization must strip null bytes and control charactersSecurity hardening for user-facing password input

Technical Debt

ItemPriorityNotes
Floor control (PTT) not implementedHighPhase 6 planned but not started
Mode switcher UI pendingHighCloud vs LAN/PTT mode selection not built
PeerServer hardcoded to localhost:9000MediumNeeds configuration for LAN deployment
No end-to-end encryptionMediumPlanned for v1.2
REACT_APP_ env vars in constants.jsLowLegacy CRA prefix; should be VITE_
No TypeScriptLowPlain JavaScript; TS would improve maintainability

Status

Active development — v1.1 LAN Push-to-Talk phase 5 of 7 complete. Two phases remain: Floor Control and Mode Switcher. CI/CD passing, test coverage >85%, deployed on Vercel.

  • SoundBoard — shares Web Audio API and MIME type fallback patterns
  • Tech Stack — org-wide toolchain decisions