# LobbyForge > Self-hostable, voice-first community platform with a built-in plugin SDK for live activities. **Status: Closed beta (release candidate).** Core voice/chat/DM/plugin flows work end-to-end. The 2026-09-19 beta-readiness review ([report](docs/BETA_READINESS_REVIEW.md)) came after 31 earlier audit rounds. It found and fixed moderation, voice and release-pipeline defects, all reproduced live first. Full CI/CD covers CodeQL, Trivy, RustSec, dependency audits, production TLS E2E and a real-UI voice E2E that measures WebRTC audio. Branch protection and digest-pinned deployment are in place. The remaining pre-beta items are the VPS drill steps in [docs/BETA_RELEASE.md](docs/BETA_RELEASE.md). See the [feature status table](#feature-status) for what is still alpha/experimental. LobbyForge is an open-source community platform you run on your own server. It takes the "server → channel → voice room" structure you know, and lets voice rooms run live activities — games, quizzes, watch parties — through a typed plugin SDK. | | LobbyForge | Discord | TeamSpeak | Revolt | |---|:-:|:-:|:-:|:-:| | Voice-first | ✅ | ✅ | ✅ | ❌ | | Plugin SDK (in-room activities) | ✅ | ❌¹ | ❌ | ❌ | | Self-hostable | ✅ | ❌ | ✅ | ✅ | | Guest-friendly (no account needed) | ✅ | ❌ | ❌ | ❌ | > ¹ Discord has Activities/Embedded App SDK; LobbyForge's in-room plugin > model is different but the "no plugin SDK" claim you may have read > elsewhere is not accurate. ## Feature status Honest assessment of what works today: | Feature | Status | |---------|--------| | Guest access (invite → one-click join) | ✅ Available | | Voice rooms (LiveKit audio/video/screen share) | ✅ Beta — production TLS E2E plus a real-UI voice E2E in CI (audio flow via WebRTC stats, mute/deafen, moderator server mute, PTT, listen-only fallback); TURN relay with ephemeral credentials | | Text channels + chat | ✅ Available | | Direct messages (instance-local) | ✅ Available — block enforcement, reply integrity | | Multi-server lobby switching | ✅ Available (official instance) | | Discovery directory | 🟡 Beta — account-bound proof + domain verification + key rotation; real instances needed | | Activities: Hushle, Quiz, Vampire Village, Watch Party, Poll, Dice | 🟡 Beta — server-authoritative reducers, per-viewer hidden state, late-press protection, voice-room rules, host hand-over; played end to end with 4–7 browsers | | Chat polls | ✅ Available — members with Create Polls post polls in text channels; voters stay anonymous | | Bots (Bot API v1 + v2) | ✅ Available — tokens, slash commands with options, public/ephemeral answers, signed HTTPS event endpoints, a WebSocket event stream, incoming webhooks, built-in Welcome and Moderation bots ([docs/BOTS.md](docs/BOTS.md), [docs/BOT_API_V2.md](docs/BOT_API_V2.md)) | | Plugin SDK (bundled plugins) | ✅ Available — reducers, effects (timers, storage, app chat lines), test harness | | Community plugin marketplace | 🟡 Beta — reviewed and SHA-256-pinned bundles run in a QuickJS WebAssembly sandbox in an isolated worker, UI in a sandboxed iframe ([ADR-007](docs/ARCHITECTURE_DECISIONS.md)); anything beyond the sandbox (outside sites, its own site as the UI, timers, storage, chat lines) needs the owner's approval at install ([docs/PLUGIN_UNLOCK_PLAN.md](docs/PLUGIN_UNLOCK_PLAN.md)) | | Bot protection | ✅ Available — ALTCHA by default, Turnstile or reCAPTCHA optional | | Email verification and password reset | ✅ Available — SMTP providers (SES, Scaleway and others) | | Languages | ✅ English and Turkish complete; a new language is a folder of JSON files, no code ([docs/TRANSLATING.md](docs/TRANSLATING.md)) | | Admin panel (settings, moderation, doctor) | ✅ Available | | Self-host updates (one-click upgrade) | ✅ Available — signed release manifests pin the immutable GHCR image digest; `lfctl update check/plan/apply` verifies the signature against the committed official public key, auto-creates + strictly verifies a backup, deploys exactly the signed digest, persists deployed-version state and records a rollback pointer (`lfctl update rollback`; app-level — DB migrations are forward-only) | | Backups (create/restore) | ✅ Available — streaming SHA-256, formatVersion:1 manifest, destructive restore drill in CI | | Desktop app (Tauri 2) | 🟡 Alpha — builds and runs; global PTT + shortcuts fixed in the beta review (verify on each OS); code signing deferred (see [ADR-005](docs/ARCHITECTURE_DECISIONS.md)) | | Google OAuth login | ✅ Available (opt-in via env vars) | | TURN relay | ✅ Available — coturn 4.18.0, ephemeral REST-auth credentials, IPv6 private-range denied | ## Features - **Voice rooms** powered by [LiveKit](https://livekit.io) — WebRTC SFU, mic/camera/screen-share, speaking indicators, per-user volume. - **Plugin SDK** — pure reducer pattern (`State → Action → State`), declarative action policies, server-side state projection (anti-cheat), built-in test harness. - **Bundled activities** — Hushle (Taboo-style), Quiz, Vampire Village (social deduction), Watch Party (synchronised YouTube), Poll and Dice; chat polls in text channels. - **Bots and marketplace plugins** — the Bot API (slash commands, events, webhooks) and sandboxed community plugins that ask the owner before they get more than the sandbox. - **Guest access** — invite link → one click into a voice room. No account required. - **Real-time** — WebSocket gateway + Redis pub/sub for presence, chat, DMs, and activity state. - **Game integrity** — optimistic concurrency (revision CAS), per-viewer state projection, phase-based action validation. - **Doctor** — built-in health monitoring + capacity profiling. - **Privacy-first defaults** — SEO off, invite-only registration, no telemetry, strict security headers (CSP with nonce, HSTS, Fetch-Metadata CSRF). - **i18n** — English + Turkish; community translations welcome. - **Native desktop client (optional)** — the web app is fully functional on its own; the [Tauri 2](https://v2.tauri.app) shell is an **opt-in extra** for members who want a native window, tray and global push-to-talk. Nothing to enable server-side — see the [Desktop app (optional)](#desktop-app-optional) section below. ## Tech stack - **[Next.js 16](https://nextjs.org)** (App Router) + React + TypeScript - **[LiveKit](https://livekit.io)** for WebRTC voice/video - **[PostgreSQL](https://www.postgresql.org)** + **[Drizzle ORM](https://orm.drizzle.team)** - **[Redis](https://redis.io)** for presence, pub/sub, rate limiting, ephemeral state - **[pnpm](https://pnpm.io)** monorepo workspaces - A standalone **WebSocket gateway** (`apps/ws-gateway`) for realtime fan-out ## Quick start ### Prerequisites - **Node.js ≥ 22** - **pnpm ≥ 10.12.1** (`corepack enable`) - **Docker** (for the backing services) ### 1. Start the local stack ```sh cp infra/docker/.env.example infra/docker/.env pnpm lfctl setup token # put the printed value in infra/docker/.env as LOBBYFORGE_SETUP_TOKEN docker compose -f infra/docker/docker-compose.dev.yml up -d --build ``` This builds the app image and runs **the whole stack on this machine**: PostgreSQL, Redis, LiveKit, the database migrations, the web app (a production build, `NODE_ENV=production`) and the realtime gateway, with healthchecks. Open `http://localhost:19520` and walk through the first-run setup wizard. (See `infra/docker/README.md` for the optional `--profile full` services: Mailpit, MinIO, Coturn.) > **Local only.** Every port this stack publishes is bound to `127.0.0.1`, > so nothing is reachable from your network. It runs with public > development secrets (the compose defaults and `.env.example`), which the > app accepts only because the dev compose sets `LOBBYFORGE_DEV_STACK=true`; > anywhere else, web and the gateway refuse to start with a placeholder > session secret. To run LobbyForge for other people, use the production > installer (`install.sh`, see [docs/BETA_RELEASE.md](docs/BETA_RELEASE.md)). ### 2. Work on the code (hot reload) Run only the backing services in Docker and the apps from source: ```sh pnpm install pnpm build:packages docker compose -f infra/docker/docker-compose.dev.yml stop web ws-gateway # if step 1 is running docker compose -f infra/docker/docker-compose.dev.yml up -d postgres redis livekit ``` Configure the web app in `apps/web/.env.local` (Next.js reads env files from the app's directory). The session secret must be real — placeholder values are refused: ```sh LOBBYFORGE_SESSION_SECRET=<64 random hex characters> LOBBYFORGE_SETUP_TOKEN=<64 random hex characters, a different one> DATABASE_URL=postgres://lobbyforge:lobbyforge_dev@localhost:19532/lobbyforge REDIS_URL=redis://:lobbyforge_dev@localhost:19579 ``` Generate each secret with: ```sh node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" ``` Then run: ```sh pnpm dev # all workspaces in parallel # or just the web app: pnpm --filter @lobbyforge/web dev ``` Open `http://localhost:19520` and walk through the first-run setup wizard. > Local ports sit in a quiet range so they do not collide with whatever > else you run: web `19520`, realtime gateway `19521`, LiveKit `19580` > (media `19582/udp`), Postgres `19532`, Redis `19579` — all on > `127.0.0.1`. ### Verify everything ```sh pnpm verify # typecheck + lint + test across all workspaces ``` ## Monorepo layout ``` apps/ web/ Next.js app — lobby, admin, API routes, realtime desktop/ Tauri 2 shell (experimental) plugin-worker/ Isolated QuickJS sandbox that runs marketplace plugins registry/ Instance registry service ws-gateway/ Standalone WebSocket gateway for realtime fan-out packages/ core/ Shared helpers (cookies, guest sessions, doctor, update planner) db/ Drizzle schema, queries, migrations config/ Shared build/runtime config ui/ Shared UI primitives plugin-sdk/ Plugin lifecycle, reducer types, test harness, locale bot-sdk/ Bot client: REST, slash commands, event stream, webhook signatures plugins/ hushle/ Taboo-style voice game (flagship) quiz/ Quiz game vampire-village/ Werewolf/Mafia-style social deduction watch-party/ Synchronized video watching poll/ Polls in voice rooms dice-bot/ Dice rolls examples/ plugins/sandbox-buzzer/ A marketplace (sandbox-v1) plugin: UI, sound, timers, storage ``` ## Desktop app (optional) The web app is the product — every feature (voice, games, admin, permissions) works in the browser. The native shell is an **optional client** that members install individually; **instance owners configure nothing**. **Who is it for?** Members who want a native window, system tray, and the global push-to-talk hotkey (Ctrl+Space) while another app has focus. **How a member sets it up (one-time, ~30 seconds):** 1. Download the installer for your OS from the [GitHub releases](https://github.com/Juanka-e/LobbyForge/releases) page. 2. Install and launch it. 3. Enter your community's URL (e.g. `https://my.lobbyforge.dev`) — the same address you use in the browser. That's it; the URL is remembered. One installer works with **any** LobbyForge instance — there is no per-instance build or server-side switch. Switching communities is just entering a different URL. **Status: experimental alpha.** Installers are not code-signed yet, so: - **Windows:** SmartScreen shows "Windows protected your PC" — *More info → Run anyway*. - **macOS:** Gatekeeper blocks unsigned apps — right-click → *Open*, or run `xattr -cr /Applications/LobbyForge.app` after dragging to Applications. Details: [docs/DESKTOP.md](docs/DESKTOP.md) · [docs/DESKTOP_GAP_ANALYSIS.md](docs/DESKTOP_GAP_ANALYSIS.md) ## Documentation - **[docs/MONOREPO.md](docs/MONOREPO.md)** — workspace structure and cross-platform usage - **[docs/WEB_APP.md](docs/WEB_APP.md)** — the Next.js app in detail - **[docs/PLUGIN_SDK.md](docs/PLUGIN_SDK.md)** — how to write a plugin - **[docs/DOCTOR.md](docs/DOCTOR.md)** — health & capacity monitoring - **[docs/VOICE_TURN.md](docs/VOICE_TURN.md)** — production voice networking: coturn TURN fallback, firewall ports, NAT test matrix - **[docs/CONTRIBUTING.md](docs/CONTRIBUTING.md)** — how to contribute - **[docs/CHANGELOG.md](docs/CHANGELOG.md)** — full change history ## Contributing See **[docs/CONTRIBUTING.md](docs/CONTRIBUTING.md)**. TL;DR: Node ≥ 22, pnpm ≥ 10.12.1, run `pnpm verify` before pushing. No `&&` in scripts (cross-platform), always include `.js` extensions on relative ESM imports. ## License [AGPL-3.0-only](LICENSE) — open source. Self-host freely; derivative services must stay open.