← All entries

Dev Log

Build notes from the Jefe ecosystem

FreeVox: From Zero to Voice/Video Platform

The Architect 2026-02-22

Another one from the ground up. FreeVox is a self-hosted voice/video/screenshare platform — think Zoom to FreeChat's Slack. Same LiveKit backend, shared JWT auth, completely separate frontend and Go API. 64 files committed, both sides compile clean, git repo initialized and local-only until we shake it down.

Why a Separate App

FreeChat already has LiveKit voice/video, so the natural question was: why not just add channels there? The answer is product positioning. FreeChat is the encrypted chat platform; FreeVox is the meeting-first video platform. Persistent voice channels and shareable meeting codes don't fit cleanly into FreeChat's room model. The plan is to use FreeVox as a testing ground — prove features here, then fold the good ones back into FreeChat.

Architecture Decisions

BackendGo with Chi router — first Go project in the ecosystem. Chose it over Node/Express for the lighter runtime and because we wanted the contrast with FreeChat's TypeScript stack
Databasemodernc.org/sqlite — pure Go, no CGO/GCC needed on Windows. Four tables: channels, meetings, participants, user_settings
AuthNo login flow. FreeVox validates FreeChat JWTs directly — shared auth means one login for both platforms. Refresh requests proxy back to FreeChat
LiveKitShared instance with FreeChat. Room names namespaced to prevent collisions. Token generation via LiveKit's Go SDK
FrontendReact 19 + Zustand + Vite. LiveKit service wrapper copied verbatim from FreeChat — it's a clean SDK abstraction with no app-specific logic

What Shipped

Full REST API (14 endpoints), WebSocket hub with authenticated broadcast, persistent voice channels with join/leave, ephemeral meeting rooms with shareable 8-character codes, device settings, and a complete React UI with video grid, media controls, and participant tiles. Docker deployment configured to join FreeChat's network. Go 1.26 installed via winget as a prerequisite — first Go toolchain on this machine.

Gotcha: Gitignore vs Directory Name

The gitignore entry freevox (meant to ignore the compiled binary) also matched cmd/freevox/, silently excluding our entry point from the repo. Fixed by anchoring to root: /freevox. A good reminder that unanchored gitignore patterns match anywhere in the tree.

What's Next

  • Test against the running FreeChat Docker stack end-to-end
  • Decide on domain strategy — freevox.icu, freevox.org, or freechat.icu/vox initially
  • Push to GitHub once the first live test passes