Every gaming PC running CR Cafe has a small Electron app on it: the station agent. Its main job is a full-screen lock screen that stays up until a session starts. A lock screen is only useful if it can’t be got around, and that turned out to depend on details that no amount of testing on a developer machine would reveal.
Why Electron
The agent needs a polished, branded screen, a persistent Socket.IO connection to the backend, access to Windows for power, input and policy, and an update channel. Electron gives us all of that in the same language as the rest of the platform, so the team that builds the dashboard can build the agent.
The upgrade that broke the kiosk
Our Electron version was old enough to carry published security advisories, so we upgraded. On a real station the lock window came up covering only part of the display. The taskbar, desktop icons and game launchers were reachable around it — the kiosk guarantee, gone.
Logs from the station showed the window being created at roughly 800×600: Electron’s default size. The fullscreen and kiosk flags passed at construction were simply being ignored in the newer versions. None of the documented breaking changes explained it, and in development everything looked fine, because the setup window is an ordinary window that never exercises the kiosk path.
The fix: never trust, always enforce
- Create the lock window at the display’s real bounds — explicit x, y, width and height — so it is never created wrong
- Re-check the window against those bounds at runtime and force it back if a resolution change or anything else moves it
- Compare against the display’s full bounds, never the work area, which excludes the taskbar
One tempting “improvement” made things worse: trusting isFullScreen(). A station logged a window 41 pixels short of the screen height — exactly the taskbar — while isFullScreen() returned true. On Windows, “full screen” can mean full to the work area. An exact bounds comparison is the only test that catches it.
Updates that don’t interrupt anyone
The agent updates itself with electron-updater. Two rules came from production. First, it only downloads and installs while the station is locked, so nobody’s session is interrupted. Second, update checks are spread out randomly instead of on a fixed clock: a customer once reported in-game ping going from 8 ms to 1000 ms because every machine in the cafe was pulling an installer over the same connection at the same moment.
An escape hatch that works offline
The dashboard is in the cloud, so an internet outage takes it offline at the same moment the stations lose their connection. Staff therefore have an offline unlock: a passphrase whose hash the agent keeps locally and verifies without the server. Each offline unlock is queued and reported when the connection returns, and a restart relocks the PC.
Lessons
- Test kiosk and window behaviour on the real hardware, packaged, before shipping
- Treat window-manager flags as requests, not guarantees
- Design updates around the user’s session and the shared network, not just the code
- Anything safety-critical needs an offline path
More on the whole system is in the CR Cafe case study. If you need desktop software alongside a web platform, that is part of our custom software development work.
