webapp: add /onboard wizard — web equivalent of php artisan rig:loading

Browser-based Project Loading manifest builder at http://127.0.0.1:1118/onboard.
Reuses the existing terminal/CRT styling (hud.css palette + scanlines +
phosphor glow) so it doesn't feel like a separate UI:

 - GET  /onboard           — the wizard, seeded from current loading.json
 - GET  /onboard/search?q= — type-ahead Twitch search/categories proxy
 - POST /onboard           — writes storage/data/loading.json, optionally
                              pushes the title + category via TwitchHelix

UX: prompt-line inputs, ↑/↓/Enter on the search dropdown, stepper for the
countdown, ENABLED/DISABLED toggles for camera + microphone, a live
right-pane preview that renders the same lines the loading overlay's
terminal will type. CSRF-exempt POST so the page can submit JSON without
a token round-trip.

Falls back gracefully when TWITCH_CLIENT_ID / TWITCH_TOKEN are absent —
the search is disabled and the manifest still saves locally.
This commit is contained in:
Jakub Zych
2026-05-21 13:49:19 +02:00
parent b47f8fca83
commit 4ceff4015a
4 changed files with 912 additions and 0 deletions

View File

@@ -3,6 +3,7 @@
use App\Http\Controllers\AudioController;
use App\Http\Controllers\DataController;
use App\Http\Controllers\MusicCommandController;
use App\Http\Controllers\OnboardController;
use App\Http\Controllers\Overlays\DesktopController;
use App\Http\Controllers\Overlays\GameController;
use App\Http\Controllers\Overlays\GoodbyeController;
@@ -34,3 +35,7 @@ Route::get('/track', [AudioController::class, 'stream']);
Route::post('/cmd/{type}', [MusicCommandController::class, 'send'])
->whereIn('type', ['skip', 'prev', 'pause', 'resume']);
Route::get('/onboard', [OnboardController::class, 'show']);
Route::get('/onboard/search', [OnboardController::class, 'search']);
Route::post('/onboard', [OnboardController::class, 'submit']);