diff --git a/crates/wzp-web/src/main.rs b/crates/wzp-web/src/main.rs index 56f2a5e..f669383 100644 --- a/crates/wzp-web/src/main.rs +++ b/crates/wzp-web/src/main.rs @@ -99,10 +99,17 @@ async fn main() -> anyhow::Result<()> { "static" }; + // Serve index.html for any path that isn't /ws/, /metrics, or a static file. + // This lets URLs like /manwe load the SPA which reads the room from the path. + let static_service = ServeDir::new(static_dir) + .fallback(tower_http::services::ServeFile::new( + format!("{}/index.html", static_dir), + )); + let app = Router::new() .route("/ws/{room}", get(ws_handler)) .route("/metrics", get(metrics::metrics_handler)) - .fallback_service(ServeDir::new(static_dir)) + .fallback_service(static_service) .with_state(state); let listen: SocketAddr = format!("0.0.0.0:{port}").parse()?; diff --git a/crates/wzp-web/static/index.html b/crates/wzp-web/static/index.html index 383de72..ccaba0f 100644 --- a/crates/wzp-web/static/index.html +++ b/crates/wzp-web/static/index.html @@ -66,7 +66,6 @@ let statsInterval = null; // Use room from URL path or input field function getRoom() { - // Check URL: /roomname or /#roomname const path = location.pathname.replace(/^\//, '').replace(/\/$/, ''); if (path && path !== 'index.html') return path; const hash = location.hash.replace('#', ''); @@ -74,6 +73,14 @@ function getRoom() { return document.getElementById('room').value.trim() || 'default'; } +// Pre-fill room input from URL on page load +(function() { + const path = location.pathname.replace(/^\//, '').replace(/\/$/, ''); + if (path && path !== 'index.html') { + document.getElementById('room').value = path; + } +})(); + function setStatus(msg) { document.getElementById('status').textContent = msg; } function setStats(msg) { document.getElementById('stats').textContent = msg; }