Files
obs-config/webapp

OPHI-118 webapp

Laravel app that renders every on-stream overlay for the OPHI-118 Twitch rig and hosts the streamer's control surfaces. Runs under supervisord on http://127.0.0.1:1118/.

Looking for the rig-wide picture (OBS, MPD, twitch-bot, deployment)? See ../README.md. This file is just the webapp.

What's in here

Control panel — /

Tile-based dashboard. Entry point from a browser bookmark; not used by OBS itself.

Control panel

  • ONBOARD — opens the project-loading wizard.
  • SCENES — opens the full route index.
  • ophi118.com — public channel landing page.
  • gamez.ciemnosc.com — self-hosted game-server roster.

Onboard wizard — /onboard

Web equivalent of php artisan rig:loading. Compiles the Project Loading manifest (game, subtitle, countdown, camera/mic state) and optionally pushes the channel title + category to Twitch via Helix.

Onboard form

  • Type-ahead game search against the Twitch Helix search/categories endpoint, debounced. ↑/↓/Enter/Esc keys to pick a match; locks the gameId.
  • Live preview mirrors what the /loading overlay will render — every edit re-renders the terminal-style output immediately.
  • Stepper for the countdown, ENABLED/DISABLED toggles for camera/mic, push-to-Twitch checkbox to commit the channel update via Helix.
  • Graceful fallback: with TWITCH_CLIENT_ID / TWITCH_ACCESS_TOKEN unset, the search disables and the manifest still saves locally.

Onboard preview

Scenes index — /scenes

All overlay URLs the OBS browser-sources point at, plus the data endpoints.

Scenes

Overlay routes

Browser sources in basic/scenes/Default_Stream_HUD.json consume these. Edits to the Blade views are picked up on the next OBS Refresh cache — no server restart needed.

Route Purpose
/landing Fallout-style "PLEASE STAND BY" + telemetry rotator
/loading Terminal-style Project Loading + countdown
/game Game HUD (camera-frame OBS-WS sync, status bar)
/desktop Desktop HUD (camera + screen-capture frames)
/goodbye Sign-off terminal + "OFFLINE FOR" counter
/music-box Full-screen music box terminal
/music-box/widget Compact 549×880 widget
/music-box/cover Album-art widget (?bars=0 for compact mode)
/music-box/nc ncurses-styled 2-pane variant
/music-daemon Passive WebSocket listener (diagnostic)

Data + control endpoints

Route Notes
GET /data/playlist.js Returns window.__PLAYLIST = {...}; with ETag
GET /cover.jpg Streams bridges/cover.jpg (kept fresh by mpd-state.py)
GET /track?p=<base64> Audio stream — path-traversal-guarded
POST /cmd/{skip|prev|pause|resume} Broadcasts mpd:cmd over OBS WebSocket

Artisan commands

Each lives at app/Console/Commands/Rig*Command.php. Run from the webapp/ directory.

php artisan rig:setup            # gen public/js/obs-config.js + OBS_WS_* in .env
php artisan rig:telemetry        # refresh storage/data/telemetry.json
php artisan rig:telemetry --collect   # re-prompt every field interactively
php artisan rig:loading          # interactive Project Loading manifest (CLI mirror of /onboard)
php artisan rig:playlist         # reindex audio dirs → storage/data/playlist.json
php artisan rig:cmd skip         # CLI mirror of POST /cmd/skip

Running it

The supervisord program file lives at ../scripts/obs-webapp.supervisord.conf and is installed (root-owned) to /etc/supervisor.d/obs-webapp.conf by scripts/deploy-rig.sh.

sudo supervisorctl status obs-webapp        # → RUNNING
sudo supervisorctl restart obs-webapp       # after route / controller / .env changes
tail -F storage/logs/supervisord.{out,err}.log

For local hacking without supervisord:

php artisan serve --host=127.0.0.1 --port=1118

When to restart

Change Action
Blade view (resources/views/) OBS → right-click source → Refresh cache
Static CSS / JS (public/) Same — Refresh cache
Route / controller / service / config / .env sudo supervisorctl restart obs-webapp

Layout

webapp/
├── app/
│   ├── Console/Commands/        rig:setup, rig:telemetry, rig:loading,
│   │                            rig:playlist, rig:cmd
│   ├── Http/Controllers/        Overlays/{Landing,Loading,Game,Desktop,
│   │                            Goodbye,MusicBox,MusicDaemon}, Data,
│   │                            MusicCommand, Audio, Onboard
│   ├── Services/                ObsWsClient (Pawl), TwitchHelix,
│   │                            HardwareSnapshot
│   └── Support/RigData.php
├── resources/
│   ├── views/
│   │   ├── home.blade.php       /
│   │   ├── scenes.blade.php     /scenes
│   │   ├── onboard.blade.php    /onboard
│   │   ├── overlays/            per-scene overlays
│   │   ├── partials/            topbar, hud-strip, crt-overlays, …
│   │   └── layouts/             overlay base layout
│   └── img/                     favicon + screenshots (this README)
├── public/
│   ├── css/hud.css              shared HUD chrome, scanlines, terminal styling
│   ├── js/                      hud, crt-static, obs-ws-bootstrap, obs-ws-mini
│   ├── audio/static-hum.wav     ffmpeg_source (not browser-served)
│   └── favicon.ico              → symlink to ../resources/img/favicon.ico
├── routes/web.php
├── config/rig.php               storage paths, OBS WS creds, Twitch keys
└── storage/data/                rig:* commands write JSON here
    ├── loading.json
    ├── playlist.json
    └── telemetry.json

Config

.env keys the webapp cares about:

APP_URL=http://127.0.0.1:1118

OBS_WS_URL=ws://localhost:4455
OBS_WS_PASSWORD=…                # written by `php artisan rig:setup`

TWITCH_CLIENT_ID=…
TWITCH_ACCESS_TOKEN=…            # legacy TWITCH_TOKEN is also accepted
TWITCH_BROADCASTER_ID=…

RIG_NAME=…
OBS_PROFILE=ophi118
MUSIC_DIR_1=…

See .env.example for the full set.