Sebelumnya tombol Live/Muted cuma kirim voice:transmit:start/stop ke gateway — TIDAK ADA audio yang dikirim (0 getUserMedia/AudioContext di frontend). MicControl cuma toggle state kosong. - lib/audio/mic-transmit.ts (BARU): getUserMedia → AudioContext 48kHz → AudioWorklet (downsample 24kHz mono s16le + volume + chunk 20ms) → frame 'PCM\0' + Int16LE → ws.sendBinary. Worklet inline via Blob URL (aman untuk static export). - useMicTransmit(ws): aktif = start capture + voice:transmit:start; nonaktif = stop capture + voice:transmit:stop; setVolume untuk slider. - voice page: volume slider sekarang beneran ngatur gain mic; disconnect ikut matiin mic. Verifikasi: tsc PASS, biome 0 error, next build PASS. Test mic butuh real device (headless browser tidak punya mic) — protokol: connect voice → Live → ngomong → orang di channel denger.
Bete Frontend
Next.js 16 (React 19) dashboard untuk Discord Moderation Watcher.
Stack: Next.js 16 (App Router, static export), React 19, TypeScript strict, Tailwind v4, shadcn/ui, base-ui, lucide-react.
Dev
bun run dev # next dev — port 3000
bun run build # next build — static export ke out/
bun run lint # Biome check
Architecture
src/
├── app/ # Pages
│ ├── page.tsx # Redirect ke /dashboard
│ └── dashboard/ # Dashboard layout + tabs
│ ├── layout.tsx # Sidebar, header, WS provider, chatbot
│ └── page.tsx # Tab routing (messages/live/dashboard)
├── features/
│ ├── messages/ # Message feed, search, review, detail modal
│ ├── live/ # Voice connection, music player, recordings
│ ├── dashboard/ # Stats, users, channels overview
│ └── chatbot/ # AI chatbot
├── lib/
│ ├── api/ # Fetch-based API client (all BE endpoints)
│ ├── ws/ # WebSocket client + React context
│ └── hooks/ # Shared hooks (config, auth)
└── components/
└── layout/ # Sidebar, header, mobile tab bar
API
Backend berjalan di port 3001. Frontend mengakses API via window.location (same-origin atau proxy).
WebSocket terhubung otomatis ke /ws di host yang sama.