Architecture Overview
How the OpenNOW Electron client, renderer WebRTC path, and native streamer fit together
OpenNOW is an Electron app with three always-present Electron layers and an optional experimental Rust native streamer child process on supported desktop platforms. Electron owns authentication, session lifecycle, and signaling in both streaming modes.
Source layout
opennow-stable/src/
├── main/ Electron main process
│ ├── platforms/gfn/ OAuth, service URLs, catalog, CloudMatch, NVST transport
│ ├── ipc/ focused account/catalog, session, and media IPC handlers
│ ├── session/ Cloud G-Sync preference, session conflict, selection/lifecycle helpers
│ ├── signaling/ signaling IPC coordinator and native-streamer bridge
│ ├── media/ screenshots, recordings, thumbnails, media file helpers
│ ├── services/ PrintedWaste queue metadata, region ping, request timeout/cache services
│ ├── nativeStreamer/ Rust child-process lifecycle plus input/surface helpers
│ ├── mediaPaths.ts trusted OpenNOW media URL protocol
│ ├── discordRpc.ts Discord Rich Presence lifecycle
│ ├── appBuildInfo.ts app version, embedded build number, and commit metadata
│ ├── updater.ts update checks and electron-updater integration
│ ├── settings.ts settings defaults, migration, compatibility normalization
│ └── index.ts app bootstrap, Chromium/WebRTC flags, windows, protocol/services wiring
├── preload/ typed contextBridge surface
├── renderer/src/
│ ├── components/ app pages, StreamView, SettingsPage, queue server modal, controller library
│ ├── platforms/gfn/ renderer WebRTC client, SDP/NVST helpers, input protocol, microphone
│ ├── hooks/ reusable runtime hooks, including queue ad playback/reporting
│ └── utils/ diagnostics and UI helpers
└── shared/ IPC names, Settings, native streamer protocol/types, GFN models
native/opennow-streamer/ Rust child process with stub and modular GStreamer backendProcess responsibilities
| Layer | Responsibilities |
|---|---|
| Main process | OAuth/PKCE, provider discovery, CloudMatch create/poll/claim/stop, queue/server selection state, WebSocket signaling, settings, build metadata/updater, Discord Rich Presence, media storage, native streamer process lifecycle |
| Preload | Narrow window.openNow API over IPC; isolates renderer from Node.js APIs |
| Renderer | React app, login/library/settings, queue and launch UI, controller mode, shortcuts, renderer WebRTC playback, stats overlay, screenshots/recordings |
| Native streamer (optional, experimental) | Rust JSON-lines protocol v3 child process in the app; GStreamer webrtcbin offer/answer, local ICE, input data channels, platform video decode/render, stall/transition/stats diagnostics, and Windows native shortcut/input capture |
Streaming data flow
| Flow | Main process | Renderer | Native streamer |
|---|---|---|---|
| Auth | Opens browser/callback server, exchanges and refreshes tokens | Starts login/logout, displays auth state | Not involved |
| Launch | Creates session, polls queue, handles server selector, claims session, normalizes CloudMatch errors | Shows launch/queue state, including membership-upgrade errors from GFN playability responses | Receives session context only in native mode |
| Signaling | Connects NVST WebSocket, receives offer/ICE, sends answers/candidates | Web mode: creates answer and local ICE | Native mode: receives offer command, returns answer and local ICE events |
| Streaming | Chooses web vs experimental native mode on supported desktop platforms; normalizes native mode back to web on unsupported platforms and falls back when native is unavailable | Web mode: Chromium RTCPeerConnection, <video>/<audio>, input channels, stats | Native mode: GStreamer webrtcbin, platform decode/render, input readiness, native stats/events |
| Input | Provides IPC helpers and forwards native commands | Captures keyboard/mouse/gamepad/clipboard; web mode sends over data channels | Native mode sends encoded input after input-ready; Windows also has native OS-level input capture and shortcut reporting |
| Media | Writes screenshots/recordings and thumbnails | Renderer capture via canvas/MediaRecorder | Native external renderer has separate capture limitations |
| Settings | Loads, migrates, normalizes, persists settings.json | Renders settings UI | Receives selected native settings as environment/session context |
WebRTC renderer path
The default streamClientMode is web. The renderer owns RTCPeerConnection, SDP munging, NVST SDP generation, audio/video element playback, microphone capture, and data channels. Chromium acceleration flags are configured by the main process before app startup through videoAcceleration.ts: Windows D3D11/Media Foundation, Linux x64 VA-API plus Linux GL/zero-copy/NVIDIA VA-API flags, Linux ARM V4L2/direct decoder, macOS VideoToolbox, MP4 MediaRecorder support, dav1d AV1 fallback, disabled mDNS ICE candidates, ignored GPU blocklists, and unthrottled renderer behavior. The Settings codec diagnostics use Chromium capability reports and show a Linux VA-API setup hint when GPU decode/encode or H.265 support is still missing.
Native streamer path
When experimental native mode is selected on a supported desktop platform, the main process starts opennow-streamer, performs a protocol hello, sends start/offer/ICE/input/surface/bitrate/update-shortcuts/stopcommands, and receivesready/answerresponses plus async status, local ICE, input readiness, shortcut, video liveness, stats, and error events. The shipped media backend is Rust + GStreamerwebrtcbin`; unsupported platforms, unsupported builds, or unavailable backends report fallback details so the app can return to the web streamer path.
Key source files
| File | Purpose |
|---|---|
opennow-stable/src/main/index.ts | App bootstrap, windows, protocol/services wiring |
opennow-stable/src/main/videoAcceleration.ts | Chromium/WebRTC acceleration feature and switch selection |
opennow-stable/src/main/ipc/accountCatalogHandlers.ts | Auth/account/catalog/cache/community IPC |
opennow-stable/src/main/ipc/sessionHandlers.ts | Create/poll/claim/stop/session-ad IPC |
opennow-stable/src/main/ipc/mediaHandlers.ts | Screenshot, recording, and media gallery IPC |
opennow-stable/src/main/signaling/signalingCoordinator.ts | Signaling IPC coordination and native-streamer bridge |
opennow-stable/src/main/session/*.ts | Cloud G-Sync preference, active-session conflict handling, session selection/lifecycle helpers |
opennow-stable/src/main/media/*.ts | Screenshot/recording persistence, media file validation, thumbnail helpers |
opennow-stable/src/main/mediaPaths.ts | Trusted OpenNOW media path resolution and playback URL protocol |
opennow-stable/src/main/services/*.ts | PrintedWaste queue metadata, region ping, request timeout/cache services |
opennow-stable/src/main/platforms/gfn/auth.ts | OAuth + PKCE, token refresh, provider discovery |
opennow-stable/src/main/platforms/gfn/cloudmatch.ts | Session creation, queue polling, claim, stop |
opennow-stable/src/main/platforms/gfn/signaling.ts | NVST WebSocket signaling client |
opennow-stable/src/main/nativeStreamer/manager.ts | Native executable lookup, environment, protocol lifecycle, fallback |
opennow-stable/src/main/nativeStreamer/input.ts, surface.ts | Native input and render-surface normalization |
opennow-stable/src/main/discordRpc.ts | Discord Rich Presence updates |
opennow-stable/src/main/appBuildInfo.ts | App version, embedded build number, and commit metadata |
opennow-stable/src/main/updater.ts | Automatic update checks |
opennow-stable/src/main/settings.ts | Settings defaults and compatibility normalization |
opennow-stable/src/renderer/src/platforms/gfn/webrtcClient.ts | Renderer WebRTC peer connection, data channels, stats |
opennow-stable/src/renderer/src/platforms/gfn/sdp.ts | SDP and NVST SDP helpers |
opennow-stable/src/renderer/src/lib/codecDiagnostics.ts | Browser codec capability tests and Linux hardware-acceleration hint logic |
opennow-stable/src/renderer/src/hooks/useQueueAdRuntime.ts | Queue ad playback/reporting watchdog runtime |
opennow-stable/src/renderer/src/components/QueueServerSelectModal.tsx | Queue server selection UI |
opennow-stable/src/renderer/src/components/controllerMode/ControllerLibraryPage.tsx | Controller-first library page |
opennow-stable/src/renderer/src/components/controllerMode/controllerLibrary/ControllerLibraryLayout.tsx | Controller library layout and navigation |
opennow-stable/src/shared/gfn/ | Shared settings, session, stream, native, and API types |
opennow-stable/src/shared/nativeStreamer.ts | TypeScript protocol v3 definitions |
native/opennow-streamer/src/protocol.rs | Rust protocol/session structs |
native/opennow-streamer/src/backend.rs | Backend selection and stub fallback |
native/opennow-streamer/src/gstreamer_backend.rs | GStreamer backend orchestration |
native/opennow-streamer/src/gstreamer_pipeline.rs | GStreamer webrtcbin pipeline construction and negotiation |
native/opennow-streamer/src/gstreamer_input.rs, gstreamer_liveness.rs, gstreamer_platform.rs, gstreamer_transitions.rs, gstreamer_config.rs | Input channels, liveness diagnostics, platform paths, transition telemetry, backend configuration |