Documentation
Customization
Lights Pi is designed as a generic platform. Each deployment can be branded for a specific studio, venue, or production without modifying tracked source files.
Custom Logo
Both the landing page (port 80) and control server (port 5000) support a custom logo. Logo files are gitignored so each deployment maintains its own identity.
Adding Your Logo
Drop a file named logo.<ext> into the appropriate directory:
| Interface | Directory | Served at |
|---|---|---|
Control Server (:5000) | control-server/static/logo.<ext> | /logo |
Landing Page (:80) | landing/logo.<ext> | /logo.<ext> (nginx) |
Supported formats (priority order): .webp, .png, .svg, .jpg
If no logo file exists, both interfaces show the default SVG light-bulb icon.
Deploying the Logo
1# 1. Copy your logo into both locations locally
2cp your-logo.webp control-server/static/logo.webp
3cp your-logo.webp landing/logo.webp
4
5# 2. Deploy control server (includes static/ directory)
6bash scripts/deploy.sh
7
8# 3. Deploy landing page HTML
9./lightsctl.sh landing-deploy
10
11# 4. Push the logo to nginx (landing page serves from /var/www/html/)
12scp landing/logo.webp pi@lights.local:/tmp/logo.webp
13ssh pi@lights.local 'sudo mv /tmp/logo.webp /var/www/html/logo.webp'Logo Recommendations
- Format: WebP for smallest size with transparency support
- Dimensions: At least 96×96px for retina displays
- Shape: Square or circular (displayed with
border-radius: 50%) - Background: Transparent or dark (matches the dark UI theme)
How It Works
The /logo route in app.py scans control-server/static/ for any file
matching logo.* and serves the first match. The HTML template uses an <img>
tag with an onerror handler that reveals the fallback SVG icon if no custom
logo is found.
Landing Page Branding
The landing page text is customizable through .env variables:
| Variable | Default | Description |
|---|---|---|
LANDING_TITLE | Lighting Controller | Browser tab title |
LANDING_STUDIO_NAME | Your Studio | Main heading |
LANDING_SUBTITLE | Lighting Controller | Subtitle |
LANDING_BUTTON_TEXT | Lighting Control | Primary button |
LANDING_FOOTER_TEXT | lights.local | Footer text |
QLC_URL | http://lights.local:9999/ | QLC+ button URL |
After editing .env:
./lightsctl.sh landing-deployQLC+ Workspace Compatibility
The Pi runs QLC+ 4.14.1. If you edit workspaces on a desktop running QLC+ 5.x, the file format is incompatible and the web UI will appear blank.
Version Differences
| Feature | QLC+ 4.x | QLC+ 5.x |
|---|---|---|
<Version> tag | 4.14.1 | 5.x.x |
<BeatGenerator> | ❌ Not supported | ✅ Included |
<Palette> elements | ❌ Not supported | ✅ Included |
| Namespace prefixes | Bare elements | ns0: prefixes possible |
| Output UID | Device-specific string | May use "None" |
Converting a v5 Workspace to v4
- Change
<Version>5.x.x</Version>to<Version>4.14.1</Version> - Remove all
<BeatGenerator .../>elements - Remove all
<Palette .../>elements - Add
<SimpleDesk><Engine/></SimpleDesk>before</Workspace>if missing - Optionally remove the
UIDattribute from<Output>(let QLC+ auto-detect)
Autostart Convention
QLC+ 4.14.1 loads workspaces from ~/.qlcplus/autostart.qxw on startup.
Important: this must be a real file, not a symlink (QLC+ 4.14.1 ignores
symlinks for autostart).
The deploy-workspace command handles this correctly, placing copies at both
default.qxw and autostart.qxw.
Diagnostic Scripts
The scripts/debug/ directory includes tools for workspace issues:
| Script | Purpose |
|---|---|
fix_qlc_workspace_autoload.sh | Ensures autostart.qxw is a real file, restarts QLC+, probes WebSocket |
fix_qlc_service.sh | Updates systemd service with USB timing fixes |
push_workspace.sh | Deploys workspace as both default + autostart, verifies fixture load |
probe_qlc_ws.py | Raw WebSocket probe to discover QLC+ API message format |
UI Theme
The control server uses CSS custom properties. The default is a dark theme with
a tungsten-amber accent. Key variables in templates/index.html:
| Variable | Default | Purpose |
|---|---|---|
--ink | #0a0a0a | Page background |
--paper | #f0f0f0 | Primary text |
--amber-tungsten | #d97757 | Brand accent |
--arc-cyan | #76e8ff | Live/streaming indicator |
Pi Hostname
The hostname affects mDNS and Tailscale MagicDNS. Set during provisioning via
PI_HOSTNAME in .env:
PI_HOSTNAME=lights # → lights.local, lights.<tailnet>.ts.netTo change after provisioning:
./lightsctl.sh ssh
sudo hostnamectl set-hostname lights
sudo rebootWas this page helpful?