- TypeScript 83.7%
- Shell 7.7%
- JavaScript 7.3%
- Rust 0.4%
- CSS 0.4%
- Other 0.4%
| .codewhale | ||
| .fanout | ||
| .github/workflows | ||
| .husky | ||
| apps | ||
| artifacts | ||
| bots/github-release-bot | ||
| contracts | ||
| docs | ||
| scripts | ||
| specs | ||
| tools | ||
| .env.dev.example | ||
| .env.example | ||
| .gitignore | ||
| .phase | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| docker-compose.dev.yml | ||
| docker-compose.yml | ||
| LICENSE | ||
| livekit.dev.yaml | ||
| livekit.yaml.tmpl | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
OpenChat
A self-hosted, communication platform: real-time text, and voice/video calls. Built to integrate an existing self-hosted stack — an OpenID Connect provider (e.g. Authentik) for SSO, OpenShare for file uploads & media, and (optionally) Jellyfin for watch parties — rather than reinvent them.
OpenShare is the companion file service. Deploy it alongside OpenChat and point
SHARE_BASE_URLat it to enable image/file attachments, avatars, and inline embeds. OpenChat also runs fine without it (upload UI simply hides). Setup: docs/SETUP.md.
Everything environment-specific (domains, IPs, keys, passwords) is supplied through a single local config file — see docs/SETUP.md.
The newest versions of desktop clients for Mac, Linux, and Windows can be found on the Releases page!
If you found this project useful, consider supporting me here: https://buymeacoffee.com/minionenjoyer Thank you!
Features
- Servers, channels & folders — text + voice channels; drag-to-reorder servers and drag-to-create folders in the sidebar, persisted per user.
- Messaging — optimistic send, replies, edits, reactions, emoji, GIFs (Giphy), link/image/YouTube/Share embeds, and pinned messages with a per-channel pins panel.
- Files & media — attach files via a menu or drag-and-drop onto the window, record a voice clip in-app, click images to enlarge in a lightbox, and a custom audio player with a waveform + scrubbing (waveforms generated by OpenShare).
- Mentions —
@user, plus@here/@everyonegated behind aMENTION_EVERYONEpermission, with live toast + unread notifications. - Voice & video — self-hosted LiveKit SFU. Always-on voice channels, multi-window screen sharing (with a live viewers list), a per-server soundboard, speaking/mute indicators, voice-activity or push-to-talk input modes (with a global PTT hotkey on desktop), and per-user mic + speaker + output-volume settings.
- Presence & status — live online/offline for friends and server members, a one-click status picker (Online / Away / Do Not Disturb / Invisible), and auto-away after idle.
- User-to-user calling — ring a friend in a DM; incoming-call prompt with accept/decline and an in-conversation call banner.
- Watch parties — host-synced Jellyfin or YouTube playback inside a voice channel: host-only controls, a 👑 host badge + viewers list, and a Jellyfin browser filtered by movies / shows / music.
- Desktop apps — native Windows, macOS, and Linux clients (Tauri) with tray, notifications, global push-to-talk, drag-and-drop, and signed auto-updates. See apps/desktop/README.md.
- Roles & permissions — bitfield permissions with a data-driven role editor.
- Real-time everything — WebSocket gateway + Redis pub/sub; presence, typing, notifications, and friend/member lists update live (optimistic UI throughout).
- Mobile-tuned — responsive layout, off-canvas drawer, dynamic-viewport sizing so the composer stays above the keyboard, and a dedicated send button.
Tech stack
- Frontend: React 18 + TypeScript, Vite, Zustand,
livekit-client. Static build served by nginx. - Backend: NestJS (Node 20), Prisma, PostgreSQL 16, Redis 7 (ioredis), raw
wsgateway. - Auth: Authentik OIDC (Auth Code + PKCE), server-side Redis sessions.
- Voice: self-hosted LiveKit (WebRTC SFU), single-UDP-port mux for NAT stability.
- Deploy: Docker Compose behind an existing reverse proxy (Nginx Proxy Manager).
Repository layout
apps/api NestJS + Prisma backend (auth/OIDC, servers, channels, messages,
realtime WS gateway, voice, gifs, watch parties, Share client)
apps/web React + Vite frontend (single-page app, calls /api same-origin)
apps/desktop Tauri v2 desktop client (Win/macOS/Linux) bundling apps/web
docker-compose.yml postgres + redis + api + web + livekit
livekit.yaml.tmpl LiveKit config template (rendered to livekit.yaml from .env)
.env.example the ONE config file — copy to .env and fill in
scripts/ setup.sh (render config) · check-secrets.sh (pre-push) · deploy.sh (pull+build)
docs/ SETUP.md · DEPLOY.md · ARCHITECTURE.md
Quick start
cp .env.example .env # fill in every CHANGE_ME
./scripts/setup.sh # renders livekit.yaml from .env
docker compose up -d --build
Full instructions — including OIDC/Share/LiveKit prerequisites, local dev, pushing to git, and git-based redeploys — are in docs/SETUP.md and docs/DEPLOY.md.
Configuration & secrets
All personal data (API keys, tokens, IPs, passwords) lives only in the local, gitignored
.env (and the livekit.yaml it renders). Committed files contain generic placeholders and
public reference values only. ./scripts/check-secrets.sh verifies nothing sensitive is tracked
before you push.