Architecture
Waylo is a Node.js backend that talks to GNOME's compositor over D-Bus and to the browser over WebSocket, with GStreamer doing the video encoding in between.
Why GNOME Mutter (not xdg-desktop-portal)?
The standard portal approach can't serve unattended access: it requires a human
to approve a dialog and pick monitors on every start, and doesn't persist those
choices. Waylo instead calls Mutter's own APIs
(org.gnome.Mutter.ScreenCast and org.gnome.Mutter.RemoteDesktop) directly:
no dialogs, no manual activation, monitor selection persists, and it works
immediately across restarts.
The two sessions are linked — the ScreenCast session is created against the RemoteDesktop session's id. That link is what lets Waylo use absolute pointer positioning against the captured streams.
Backend modules
gnomeBackend.js— creates and links the Mutter RemoteDesktop + ScreenCast sessions, records each monitor, injects input, and handles locking/unlocking (including the locked-screen recovery).streamer.js— manages the GStreamer video pipeline (H.264 or MJPEG), emitting encoded frames.audioStreamer.js— Opus desktop-audio pipeline.clipboard.js— bidirectional clipboard + file-offer sync over Mutter selections.inputHandler.js— maps browser input events to evdev keycodes / keysyms and pointer/scroll notifications.auth.js— verifies credentials over SSH and performs unattended-access setup (auto-login, autolock).server.js— the HTTP + WebSocket server, session lifecycle, rate limiting, upload endpoint, and multi-client fan-out.index.js— entry point and CLI parsing.
Frontend
A Svelte + Vite single-page app, served by the backend from dist/:
- VideoStream — decodes the stream (WebCodecs for H.264,
<img>/canvas for MJPEG) and captures pointer/keyboard/touch input. - Login — credentials and per-session settings.
- Toolbar — monitor switching, fullscreen, audio, lock, settings, disconnect.
- stores/ — WebSocket connection + auth, audio, upload, download, and stats.
Session lifecycle
The backend starts capturing only after a client authenticates; the first client's login brings the Mutter/GStreamer backend up, subsequent clients and pop-out windows attach to it, and it is torn down when the last client disconnects. A client that drops reconnects and re-authenticates automatically, resuming its monitor view. See Video Pipeline for the wire format and Security for authentication.