Major Changes
Game Launcher & Launcher Detection
New @nearcade/launcher-detect package detecting Steam, Heroic, Lutris, Epic, Ubisoft Connect, Origin, and Battle.net on Linux, Windows, and macOS. Games picker UI with grid/list view, search, pinning favourites, and play-count tracking. Dashboard games ribbon slides out from the Connect panel. Host toolbar gets a game launcher button. Auto-capture triggers when a game is launched. New API endpoints: /api/games, /api/launchers, /api/launch-game, /api/game-art.
Voice Chat Overlay
New in-session voice chat overlay showing all connected users with mic status, talking indicator, accent-coloured names, and per-user mute/volume controls. Hidden by default, shown via toolbar button. Host-side VAD via RMS energy analysis on incoming mic streams, broadcasting active speakers every 500ms. Cross-viewer muting via set-viewer-volume WebSocket messages. Viewer toolbar voice toggle with animated talking pulse ring.
Host Avatar System
Avatar setting in Dashboard with Randomize button. 100 variants generated via DiceBear Big Smile style, served from /assets/avatars/avatar-{n}.svg. Synced to localStorage and server; displayed in voice overlay.
Tournament Mode
New toggle in App Settings badged "Lowest Latency". Disables Arcade pings, Discord RPC, Pusher, congestion control, dynamic bitrate, and chat. Collapses right sidebar in host shell layout to 68px.
Additional Tunnel Providers
Tunnel logic extracted to src/scripts/tunnels.js supporting bore, ngrok, frp, tailscale-funnel/serve/mesh, zerotier, netmaker, and wireguard-direct. Dashboard has collapsible Additional Tunnels settings with provider cards. New API: /api/tunnels/providers, /api/tunnels/start.
WebCodecs SVC Layers
Temporal SVC support for VP9 and AV1 WebCodecs encoders (L1T1, L1T2, L1T3). Host broadcasts decoder config with svcTemporalLayers. Viewer can request preferred layer via setSvcLayer(). Host's updateSvcLayers(n) dynamically reconfigures the encoder.
WebCodecs Frame Health Monitor
Viewer-side detection of black screen (center-pixel check), frozen stream (5s timeout), and decoder stalls. Health telemetry sent to host. After 2 critical failures, auto-fallbacks from WebCodecs to standard WebRTC.
DRM/KMS Native Capture (Wayland)
New native Linux capture via DRM/KMS forked child process (drm-worker.js) polling raw RGBA frames from GPU through canvas captureStream, bypassing xdg-desktop-portal on Wayland. New IPC handlers: drm-capture-start, drm-capture-get-frame, drm-capture-stop. Auto-capture on Wayland tries DRM first, falls back to Portal.
Input Sequence Tracking & Ack
Every viewer input gets a sequence number (_seq). Host sends input-ack every 10th input. Gamepad packets exempt from PPS flood protection. Binary gamepad packets (0x01 prefix) bypass JSON parsing on the input WebSocket.
Chat Enhancements
@-mentions with autocomplete dropdown (arrow keys, Tab/Enter). Platform badges next to names (Mobile, Steam Deck, Windows, macOS, Linux, PC). Viewer-chosen chat name colours synced to host. HOST badge on host messages. Mention highlighting with yellow left border. Chat panel now resizable.
Pre-Join Host Info Bar
When joining via ?host= URL, fetches /api/info before connecting and displays host name, game title, region, viewer count, and codec.
Latency/FPS Overlay (Viewer)
New viewer overlay showing ping (green/yellow/red), FPS, frame jitter (std dev), and connection path (Relay/P2P). Uses requestVideoFrameCallback for frame-accurate FPS and ping/pong for RTT.
Emoji Picker
New src/scripts/emoji-data.js with categorized emoji lists. Emoji picker button in host chat input with category tabs (smileys, gestures) and click-to-insert.
Signaling Module
New src/scripts/signaling.js WebSocket abstraction class used by host.js and viewer.js, replacing raw WebSocket with reconnection support, binary handling, and event-driven architecture.
Color Picker & Profile Panel (Viewer)
Native HTML color input with 8 preset swatches in the viewer join screen. Colour synced to host for chat name colour. Profile panel expandable from PIN card showing name, colour picker, and viewer ID.
Quick Host Panel (Viewer Page)
Fixed button in top-right (Electron only) opening slide-in panel with game ID input, launcher grid, and dashboard navigation.
Arcade Worker Enhancement
Delayed Discord role ping: initial webhook without ping; 15-minute follow-up pings the role if session still active. Tunnel URL whitelist for webhook security.
Electron 34
Electron bumped from ^33.0.0 to ^34.0.0.
Detailed Changes
Launcher Detection
- New @nearcade/launcher-detect npm package ^0.1.0
- Steam .acf file parsing with libraryfolders.vdf multi-directory support
- Heroic legendary/gog/nile library cache reading
- Lutris SQLite pga.db reading
- Games picker HTML with grid/list toggle, search, pinning, play-count sorting
- Dashboard games ribbon (‹ tab) with iframe overlay
- Host toolbar 🎮 launcher button with popup
- Auto-capture on game launch via /host?launch=1 redirect
- API endpoints: /api/games, /api/launchers, /api/launch-game, /api/game-art
- artCover image support for Heroic games
Voice Chat
- initVoiceChat IIFE managing vcUsers array and rendering
- vcRender builds overlay with mic/talking icons, volume sliders, mute buttons, accent-coloured names
- vcSyncMic reads window.micEnabled for local mic state
- 2s poll with render-on-change optimisation
- vcPanel and vcMini with drag-to-move localStorage persistence
- vcSetTalking and vcUpdateTalking from host broadcast
- Tournament mode support via vcSetTournament
- Roster sync via vcSyncRoster merging host viewer list with self-entry
- Viewer sends viewer-mic-ready; host creates offer on existing PC (in-place renegotiation)
- toggleMic patched for overlay state sync
- window.setUserVolume sends set-viewer-volume via WebSocket
- Server forwards set-viewer-volume with _viewerId
- Host extracts base viewer ID and calls setViewerVolume on audio element
Host Avatar
- DiceBear Big Smile avatars (100 variants) from avatars-{n}.svg
- Randomize button in Dashboard settings
- LocalStorage persistence (ns_host_avatar)
- Displayed in voice overlay roster
- Avatar credit in About section
Tournament Mode
- Toggle in App Settings with Lowest Latency badge
- Disables Arcade pings, Discord RPC, Pusher, congestion control, dynamic bitrate, chat
- App shell layout collapses sidebar to 68px
- CSS class .tournament-mode on .app-shell
- Skip renderer-side Pusher creation; clear require cache on toggle
- Apply tournament mode UI on page load
Tunnel Providers
- New src/scripts/tunnels.js module
- Providers: bore, ngrok, frp, tailscale-funnel/serve/mesh, zerotier, netmaker, wireguard-direct
- Dashboard collapsible settings section with provider cards
- Pricing, difficulty, and binary-found status per provider
- API endpoints: /api/tunnels/providers, /api/tunnels/start
- Tunnel URL whitelist for webhook dispatch
WebCodecs SVC
- Temporal SVC for VP9 and AV1 (L1T1, L1T2, L1T3)
- Host broadcasts decoder config with svcTemporalLayers
- Viewer setSvcLayer() / svc-layer-preference message
- Host updateSvcLayers(n) reconfigures encoder
WebCodecs Health Monitor
- Black screen detection via centre-pixel check
- Frozen stream detection (no frames for 5s)
- Decoder stall detection
- Health telemetry via webcodecs-health messages
- Auto-fallback to WebRTC after 2 critical failures (reload without ?wc)
DRM/KMS Capture
- drm-worker.js forked process polling raw RGBA from GPU
- Canvas captureStream pipeline bypassing xdg-desktop-portal
- IPC: drm-capture-start, drm-capture-get-frame, drm-capture-stop
- Auto-capture on Wayland: DRM first, Portal fallback with instruction overlay
- capture_linux native addon target in binding.gyp
- DRM capture activation for loading spinner
Input System
- Sequence number (_seq) on every viewer input
- Host sends input-ack every 10th input
- Gamepad packets exempt from PPS flood protection
- Binary gamepad packets (0x01 prefix) bypass JSON parsing
- New rawinput_win native addon (raw HID via hid.lib, setupapi.lib)
Chat
- @-mention autocomplete dropdown with arrow/Tab/Enter navigation
- Platform badges: Mobile, Steam Deck, Windows, macOS, Linux, PC
- Viewer colour synced to host for chat name colour
- HOST badge on host messages
- Mention highlighting with yellow left border
- Resizable chat panel (resize: both) with drag handle
- @mentions exclude own name
Viewer Enhancements
- Latency overlay: ping, FPS, jitter, connection path
- requestVideoFrameCallback for FPS measurement
- Ping/pong for RTT measurement
- Pre-join host info bar with host name, game, region, viewers, codec
- Default name format ncade_ + random string
- Session viewer ID fallback if sessionStorage unavailable
- Color picker with 8 swatches in join screen
- Profile panel with name, colour, viewer ID
- Quick Host button (Electron only) with game launcher
Dashboard
- Games ribbon (‹) with picker iframe
- Host avatar section with Randomize
- Additional Tunnels settings section
- Tab deeplinking via ?tab= parameter
- Dashboard settings model updates for avatar and tunnel providers
- Host pages updated (custom, minimal, modals, playground)
Infrastructure
- Electron ^33.0.0 to ^34.0.0 in package.json
- New @nearcade/launcher-detect ^0.1.0 dependency
- New src/scripts/signaling.js, emoji-data.js, tunnels.js modules
- binding.gyp: capture_linux native addon, rawinput_win binding
- Ristretto and HID Maestro LICENSE files bundled
- Icons migrated to currentColor for theme support
- monitor.svg redesigned with crosshair detail
- GPLv3 license shown in About section
- Config debouncing: saveSettings debounced 250ms
- Arcade URL configurable via window.NEARSEC_ARCADE_URL
- Arcade exit IPC keeps stream alive
- Log height increased to 300px
- bin/start.cmd uses exec, simplified cleanup
- Session TTL and cleanup for arcade sessions
Hotfix Update
- Fixed an issue where the frontend dropdown would fail to display the 'Custom WebCodecs' pipeline.
- Added launcher detection for GOG, itch.io, EA App, and Amazon Games.
- Added voice activity detection UI indicators for the host dashboard.
- Updated zrok tunnel configuration.