The Hub desktop app
A Discord-style desktop client for your own The Hub server, with automatic game detection in the background. It shows The Hub (chat, voice, screen share) in a window and quietly reports the game you're playing, even when the window is hidden or closed to the tray. It does not use or need Discord.
The detected game feeds The Hub's rich presence and its automatic voice reduction: people in your party (or, when no party is involved, people playing the same game) stay at full volume while everyone else is turned down.
What it does
- Background detection — every 20 seconds it reads the running processes (
taskliston Windows,pselsewhere) and matches them against a built-in map of 78 games plus Spotify and OBS. The main process does the work, so it keeps running with the window hidden. - Presence — pushes
{type, name, start}toPOST api.php?action=presencewith your presence key, and clears it when the game closes or you quit. Same contract astools/presence-helper.py. - A full client — the window loads your Hub server, with tray icon, close-to-tray, notifications, and Windows autostart.
Try it
cd desktop
npm install
npm start
On first run a Settings window opens. Enter:
- Server address — the URL you open The Hub at, e.g.
https://voice.example.com. - Presence key — in The Hub open Settings → Activity → Create a presence key, copy it, paste it.
Click Test to check the server is reachable, then Save and open The Hub. The tray menu has Open The Hub, Settings…, Detect games, Start with Windows and Quit.
Build a Windows installer
npm run dist
This produces an installer and a portable .exe under desktop/dist/. Upload the one you want to your site (or hand it out); it is a normal signed-less Windows build, so users may see a SmartScreen prompt.
Unit tests
npm test
Detection, presence payloads and config are plain Node modules (src/detect.js, src/presence.js, src/config.js) with no Electron dependency, so they run headless.
Files
src/main.js Electron lifecycle, window, tray, detection loop, permissions, IPC
src/detect.js process scan + game map matching (pure)
src/presence.js the presence HTTP client (pure)
src/config.js settings JSON in the user-data folder (pure)
src/games.json process -> game map (ported from tools/presence-helper.py)
src/preload.js context bridge for the settings window only
src/preload-main.js / preload-overlay.js bridges for The Hub window and the overlay
src/setup.html tabbed settings: Connection, Games, Overlay, Hotkeys
src/overlay.html the in-game overlay hotbar
assets/tray.png tray and window icon
test/ node:test unit tests
Custom games
Add your own processes in src/games.json (or set customGames in the config file, a map of processname to "Game name" or {"name","type"}). Keys are matched case-insensitively, without the folder or .exe.
Clipping, the overlay and the Games tab
The desktop app also hosts the in-game overlay and the game capture that feeds the clip studio in the The Hub window.
- Overlay: a small, click-through hotbar over windowed and borderless games. It shows the current game and a recording timer, with buttons for Record/Stop, Clip and Mute all, and a Tracks button that expands it into a compact mixer — every track's level, mute, hide and focus, with live meters. Global hotkeys (configurable in Settings → Hotkeys) drive the same clip recorder as the in-app studio, and the overlay remembers where you leave it per game. It is not drawn over exclusive-fullscreen games — run those in borderless mode — and it never injects into a game, so it does not trip anti-cheat (some titles still dislike overlays).
- Games tab (Settings → Games, also inside The Hub's own Settings when running as the desktop app): mark any running app as a game, and switch Clip / Overlay / Auto-record on or off per app. The Game capture grid shows live thumbnails of every screen and window, with an Automatic option that matches a window title to the detected game. The Hub's own windows are never listed, so the overlay and clip never capture themselves, and if no window matches nothing is captured rather than grabbing the wrong one.
- Rebindable shortcuts: in the desktop settings, click a hotkey field and press the keys you want (Backspace clears it). In the app, Settings → Shortcuts rebinds mute/deafen the same way, and Settings → Game overlay rebinds the global hotkeys.
- Voice shortcuts outside the app: the app mirrors your mute/deafen bindings to the desktop process and registers them as system-wide shortcuts, so they work while a game has focus (on by default; toggle under Settings → Game overlay → Voice shortcuts outside the app). Push-to-talk can do the same, but as a toggle rather than hold-to-talk, because operating systems report key presses without releases — there is no global key-up without a low-level keyboard hook, which this app deliberately avoids.
- Source selection when sharing: when you share your screen in the desktop app, a picker opens with thumbnails of every screen and window so you choose exactly what goes out. (In a normal browser, the browser's own picker is used.)
- Clip studio: in The Hub, the record button in the on-air dock (or right-click → Clip this person) opens the studio. Every track is recorded separately — each person's voice, camera, screen video and screen audio, your mic/camera, and the captured game — each with its own level, mute, solo and hide. Record, clip the last 15 seconds, then export a
.zipwith one folder per person, or a rendered composite as well. Everything is recorded and kept on your own machine; the room sees a recording indicator while it runs. - Game capture falls back to the primary screen when no window title matches, which handles borderless / windowed-fullscreen games and titles that don't carry the game name. It is checked every detection cycle, so when a minimised game is restored it switches from the screen back to the game window automatically. It never captures an unrelated window. (A truly exclusive-fullscreen or minimised game has no window to capture — the screen fallback is what shows it once it's on screen again.)
Notes
- Only Windows packaging is set up. The detection code is cross-platform; add macOS/Linux targets to
buildinpackage.jsonto ship those too. - The presence key can only change your activity, so keep it private. Revoke it any time in The Hub → Settings → Activity.