Production-ready Electron kiosk application that wraps the Xibo PWA player for easy deployment on desktop systems.
- Fullscreen display - No window chrome or decorations
- Keyboard shortcut protection - Disables system shortcuts
- Mouse cursor hiding - Auto-hides after 5 seconds of inactivity
- Navigation protection - Prevents navigation away from player
- Always on top - Cannot be minimized or covered
- Auto-start on boot - systemd user service support
- Prevent system sleep - Display stays on during playback
- System tray control - Hidden menu accessible via Ctrl+Shift+F12
- Service management - Easy enable/disable via systemd
- Video wall support - Synchronized layout transitions across multiple displays with <8ms precision
- Lead/follower architecture - CMS assigns roles via sync groups
- 12 choreography effects - Diagonal cascade, wave sweep, center-out, and more
- WebSocket relay - Token-authenticated LAN sync on the lead's HTTP port
- Offline LAN sync - Persisted config enables sync without CMS connectivity
- Multi-instance support - Run multiple displays on the same machine (
--instance=NAME)
- REST API first - Uses the Xibo CMS REST API as the primary protocol
- XMDS SOAP fallback - Falls back to XMDS SOAP when REST is unavailable
- Serves PWA files - Built-in Express server on localhost:8765
- CORS handling - Strips and re-injects CORS headers to avoid double-header issues with reverse proxies
- Zero configuration - Works out of the box
- Configurable log levels -
error,warn,info,debug,trace - Ideal for deployments - Use
debugduring initial setup to verify CMS connectivity, schedule parsing, and media downloads, then switch towarnorerrorfor production
- Persistent storage - electron-store for configuration
- Command-line arguments - Override settings at startup
- JSON config file - Easy manual editing if needed
- Config UI - Access via system tray menu
sudo dnf install xiboplayer-electron-*.rpmsudo apt install ./xiboplayer-electron_*.debOr from the APT repository:
curl -fsSL https://dl.xiboplayer.org/deb/GPG-KEY.asc | sudo gpg --dearmor -o /usr/share/keyrings/xiboplayer.gpg
echo "Types: deb
URIs: https://dl.xiboplayer.org/deb/ubuntu/24.04
Suites: ./
Signed-By: /usr/share/keyrings/xiboplayer.gpg" | sudo tee /etc/apt/sources.list.d/xiboplayer.sources
sudo apt update
sudo apt install xiboplayer-electronPlace a config file at ~/.config/xiboplayer/electron/config.json before first launch:
{
"cmsUrl": "https://your-cms.example.com",
"cmsKey": "your-cms-key",
"displayName": "Lobby Display"
}On first boot, if the player has no existing CMS configuration, it reads this file and seeds the internal store. The player then registers with the CMS and shows a setup screen while it waits for administrator authorization. Once authorized, it starts playing the scheduled content.
The file is only read when the store has no cmsUrl yet — after first boot
it is effectively ignored. CLI args always take priority.
If no config.json is present and no CLI args are provided, the player shows
a setup screen where you enter the CMS URL, key, and display name in the
browser. If registration fails (wrong URL, CMS unreachable), the player
redirects back to the setup screen automatically.
By default, new displays must be manually authorized by a CMS administrator. To skip this step, add OAuth2 API credentials to config.json — see the PWA README for full setup instructions including CMS Application configuration:
{
"cmsUrl": "https://your-cms.example.com",
"cmsKey": "your-cms-key",
"displayName": "Lobby Display",
"apiClientId": "your-client-id",
"apiClientSecret": "your-client-secret"
}You can also enter the API credentials interactively in the setup page under "Auto-authorize via API".
xiboplayer-electron --dev # Development mode (enables DevTools)
xiboplayer-electron --no-kiosk # Disable kiosk mode
xiboplayer-electron --port=8080 # Custom Express server port
xiboplayer-electron --instance=NAME # Run as named instance (isolated config/data)
xiboplayer-electron --cms-url=URL # CMS URL
xiboplayer-electron --cms-key=KEY # CMS key
xiboplayer-electron --display-name=NAME # Display nameCLI args are persisted to the internal store and survive restarts.
- CLI args — always win, written to store unconditionally
- config.json — read only on first boot (store empty)
- Setup screen — interactive fallback when nothing else is configured
| Purpose | Path |
|---|---|
| Config (electron-store, preferences) | ~/.config/xiboplayer/electron/ |
| Session data (Cache, IndexedDB, SW) | ~/.local/share/xiboplayer/electron/ |
| CMS config file for provisioning | ~/.config/xiboplayer/electron/config.json |
Default log level is WARNING (production-safe). The --dev flag automatically
sets DEBUG logging. Override via URL parameter ?logLevel=DEBUG, localStorage, or
CMS display settings. Log levels only affect logging verbosity — debug overlays
are controlled separately via controls.keyboard.debugOverlays in config.json.
| Level | Use case |
|---|---|
DEBUG |
Initial deployment — verify CMS connectivity, schedule parsing, media downloads (auto-set by --dev) |
INFO |
Normal operation |
WARNING |
Production default — only unexpected conditions |
ERROR |
Production — only failures |
NONE |
Silent |
# Run from command line
xiboplayer-electron
# Or launch from applications menu
# Applications → AudioVideo → xiboplayerEnable:
systemctl --user enable xiboplayer-electron.service
systemctl --user start xiboplayer-electron.serviceDisable:
systemctl --user stop xiboplayer-electron.service
systemctl --user disable xiboplayer-electron.serviceCheck status:
systemctl --user status xiboplayer-electron.serviceView logs:
journalctl --user -u xiboplayer-electron.service -fElectron shortcuts:
- Ctrl+Shift+F12 - Show system tray menu
- Ctrl+Shift+R - Reload player
- Ctrl+Shift+I - Toggle DevTools (dev mode only)
PWA player shortcuts (must be enabled in config.json controls section — all disabled by default):
| Key | Group | Action |
|---|---|---|
D |
debugOverlays |
Toggle download progress overlay |
T |
debugOverlays |
Toggle timeline overlay (click-to-skip supported) |
S |
setupKey |
Toggle CMS setup screen |
V |
videoControls |
Toggle native <video> controls |
→ / PageDown |
playbackControl |
Skip to next layout |
← / PageUp |
playbackControl |
Skip to previous layout |
Space |
playbackControl |
Pause / resume playback |
R |
playbackControl |
Revert to scheduled layout |
| Media keys | playbackControl |
Next/prev/pause/play (MediaSession API) |
See CONFIG.md for enabling specific control groups.
Right-click the system tray icon (or press Ctrl+Shift+F12) to access:
- Show Player
- Restart Player
- Configuration
- Auto-start on Boot
- Exit Player
Run multiple independent player instances on the same machine using --instance=NAME. Each instance gets its own config, session data, and server port:
# Instance "lobby" — default port 8765
xiboplayer-electron --instance=lobby
# Instance "cafeteria" — port 8766
xiboplayer-electron --instance=cafeteria --port=8766Each instance uses isolated paths:
| Default (no instance) | --instance=lobby |
|
|---|---|---|
| Config | ~/.config/xiboplayer/electron/ |
~/.config/xiboplayer/electron-lobby/ |
| Session data | ~/.local/share/xiboplayer/electron/ |
~/.local/share/xiboplayer/electron-lobby/ |
- Create a config for each instance:
mkdir -p ~/.config/xiboplayer/electron-lobby
cat > ~/.config/xiboplayer/electron-lobby/config.json << 'EOF'
{
"cmsUrl": "https://cms.example.com",
"cmsKey": "your-key",
"displayName": "Lobby Display",
"serverPort": 8765
}
EOF- Create a systemd service per instance:
cp ~/.config/systemd/user/xiboplayer-electron.service \
~/.config/systemd/user/xiboplayer-lobby.service
# Edit: ExecStart=/usr/bin/xiboplayer-electron --instance=lobby
systemctl --user enable --now xiboplayer-lobby.serviceEach instance registers as a separate display in the CMS.
npm install
npm run makeThis builds the RPM via electron-forge into out/make/rpm/x86_64/.
For production builds, use the external RPM spec instead.
npx electron . --dev --no-kioskThis enables:
- DEBUG log level (via
?logLevel=DEBUGURL param) - DevTools access (Ctrl+Shift+I)
- Console logging
- Error reporting
Set environment variable for verbose logging:
DEBUG=* xiboplayer-electronThe main process handles:
- Window management and kiosk mode
- Express server for serving PWA files
- System integrations (auto-launch, power management)
- Configuration storage
- IPC communication with renderer
The renderer is the PWA player loaded from http://localhost:8765:
- Uses the PWA built from
@xiboplayer/*packages (installed via npm) - Full access to PWA features (cache, offline, etc.)
- Communicates with main via IPC when needed
Security bridge between main and renderer:
- Exposes minimal API via contextBridge
- Prevents direct Node.js access
- Maintains security best practices
Built-in HTTP server:
- Serves PWA files from
resources/pwa/ - Runs on localhost:8765 (configurable)
- SPA routing support
The renderer process runs in a sandbox with:
contextIsolation: truenodeIntegration: falsesandbox: true
The PWA sets appropriate CSP headers to prevent XSS attacks.
The player enables GPU-accelerated video decode and compositing via command-line flags
(ignore-gpu-blocklist, enable-gpu-rasterization, VaapiVideoDecoder, etc.).
For hardware video decode, install the appropriate VAAPI driver for your GPU:
| GPU | Package (Fedora) | Notes |
|---|---|---|
| Intel | libva-intel-media-driver |
Works out of the box on most distros |
| AMD | mesa-va-drivers |
Included with Mesa |
| NVIDIA | libva-nvidia-driver |
RPM Fusion; bridges VAAPI → NVDEC |
Verify with vainfo:
sudo dnf install libva-utils
vainfoThe app requests minimal permissions:
- Display management (fullscreen, prevent sleep)
- Network access (HTTP server, XMDS communication)
- File system access (config and cache storage)
To change CMS connection parameters (address, key, display name) on a running player, open the setup page from any browser on the same machine:
http://localhost:8765/player/setup.html
This works even when the player is in kiosk mode. To force a full re-registration (new display):
# Wipe all config and restart — shows setup screen
rm -rf ~/.config/xiboplayer/electron
systemctl --user restart xiboplayer-electron.service# Check if port is available
ss -tlnp | grep 8765
# Try different port
xiboplayer-electron --port=8080
# Check logs
journalctl --user -u xiboplayer-electron.service -n 50# Check PWA files exist
ls -la ~/.local/share/xiboplayer/electron/pwa/
# Reinstall package
sudo dnf reinstall xiboplayer-electron-*.rpmElectron strips existing CORS headers from CMS responses and injects its own Access-Control-Allow-Origin: *, so double-header issues with reverse proxies (e.g. SWAG/nginx) are handled automatically. If you still see CORS errors, check that the CMS is reachable from the player.
# Enable lingering (user service without login)
loginctl enable-linger $USER
# Check service status
systemctl --user status xiboplayer-electron.service
# View full logs
journalctl --user -u xiboplayer-electron.service --no-pagerPress Ctrl+Shift+F12 to show system tray menu, then select "Exit Player".
Or from terminal:
pkill -f xiboplayer-electronsudo dnf remove xiboplayer-electronConfiguration files are preserved during uninstallation. To remove manually:
rm -rf ~/.config/xiboplayer/electron
rm -rf ~/.config/systemd/user/xiboplayer-electron.service
rm -rf ~/.local/share/applications/xiboplayer-electron.desktop- GitHub Issues: https://github.com/xiboplayer/xiboplayer-electron/issues
- Xibo CMS: https://xibosignage.com
- Electron: https://www.electronjs.org/
AGPL-3.0-or-later