openvibers/openvibe.live Commits

Live no longer carries the old game: OpenVibe.Games is being rewritten (its ADR-0007) and will never serve /game, /canvas or /api/game again, so the /game and /canvas redirects, the /api/game 410, the /ws/game and /ws/canvas upgrade branch, the SPA routes and their footer/nav/history special cases are gone (the paths answer 404, with no redirect; game and canvas stay reserved usernames). The home page's Games widgets (leaderboards and the canvas preview, switched off behind GAMES_HOME_WIDGETS because Games never served them) are deleted with their markup and CSS, and the network hub's Canvas card with them; the hero Game button opens openvibe.games. Leaderboards return when OpenVibe.Play serves them. Reviewed independently (VERDICT: SHIP). npm test 151/152, 1 skipped.

OP OpenVibers committed 29 Sept 2026 · 1a28261a4f · 10 files, +11 −264


Changes

ddiff --git a/public/css/features/home.css b/public/css/features/home.css
iindex 93e13b0f..ae383792 100644
---- a/public/css/features/home.css
++++ b/public/css/features/home.css
@@@ -406,51 +406,6 @@ body.egg-rainbow { animation: eggRainbow 2.6s linear; }
.home-pastes-list { grid-template-columns: 1fr; }
.home-paste-media { height: 136px; }
}
--.home-leaderboards {
-- display: grid;
-- grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr));
-- gap: 14px; margin-bottom: 32px;
--}
--.home-lb-card {
-- background: var(--bg-card); border: 1px solid var(--border);
-- border-radius: var(--radius-lg); padding: 16px; overflow: hidden;
--}
--.home-lb-title {
-- font-weight: 650; font-size: 0.88rem; margin-bottom: 10px;
-- color: var(--text-secondary);
-- display: flex; align-items: center; gap: 6px;
--}
--.home-lb-entries { display: flex; flex-direction: column; gap: 6px; }
--.home-lb-row {
-- display: flex; align-items: center; gap: 8px;
-- font-size: 0.82rem; padding: 4px 0;
-- border-bottom: 1px solid var(--border);
--}
--.home-lb-row:last-child { border-bottom: none; }
--.home-lb-rank {
-- width: 20px; text-align: center;
-- font-weight: 700; color: var(--text-muted); font-size: 0.75rem;
--}
--.home-lb-score {
-- font-weight: 600; color: var(--accent); font-size: 0.78rem;
-- white-space: nowrap;
--}
--.home-canvas-preview { margin-bottom: 32px; }
--.home-canvas-wrap {
-- display: flex; flex-direction: column; align-items: center;
-- background: var(--bg-card); border: 1px solid var(--border);
-- border-radius: var(--radius-lg); padding: 24px; text-align: center;
--}
--.home-canvas-wrap canvas {
-- max-height: 300px; width: auto;
--}
--.home-canvas-stats {
-- display: flex; gap: 24px; margin-top: 16px; flex-wrap: wrap;
-- justify-content: center;
--}
--.home-canvas-stat {
-- display: flex; flex-direction: column; align-items: center;
--}
.home-changelog-wrapper.collapsed .home-changelog-fade {
display: block;
}
ddiff --git a/public/css/style.css b/public/css/style.css
iindex dcbe2ede..075721d6 100644
---- a/public/css/style.css
++++ b/public/css/style.css
@@@ -2511,29 +2511,6 @@ a.pulse-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.founder-story-pullquote blockquote { font-size: 0.94rem; }
}
--/* ═══════════════════════════════════════════════════════════════
-- HOME — OPENVIBEGAMES LEADERBOARDS
-- ═══════════════════════════════════════════════════════════════ */
--.home-lb-title i { color: var(--accent); font-size: 0.85rem; }
--.home-lb-row:nth-child(1) .home-lb-rank { color: #ffd700; }
--.home-lb-row:nth-child(2) .home-lb-rank { color: #c0c0c0; }
--.home-lb-row:nth-child(3) .home-lb-rank { color: #cd7f32; }
--.home-lb-name {
-- flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
-- color: var(--text-primary);
--}
--
--/* ═══════════════════════════════════════════════════════════════
-- HOME — CANVAS PREVIEW
-- ═══════════════════════════════════════════════════════════════ */
--.home-canvas-stat strong {
-- font-size: 1.3rem; color: var(--accent); line-height: 1.2;
--}
--.home-canvas-stat span {
-- font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase;
-- letter-spacing: 0.5px;
--}
--
/* ═══════════════════════════════════════════════════════════════
STREAM VIEWER LAYOUT
═══════════════════════════════════════════════════════════════ */
ddiff --git a/public/index.html b/public/index.html
iindex 0f7b68ad..60b108db 100644
---- a/public/index.html
++++ b/public/index.html
@@@ -194,7 +194,7 @@
<div class="hero-cta" data-fx-viewport>
<button style="--i:0" class="hb hb-stream" onclick="currentUser ? navigate('/broadcast') : showModal('register')"><span class="hb-ico"><i class="fa-solid fa-broadcast-tower"></i></span><span class="hb-label">Stream</span><i class="fa-solid fa-chevron-right hb-go" aria-hidden="true"></i></button>
<a href="https://openvibe.tools" style="--i:1" class="hb hb-tools"><span class="hb-ico"><i class="fa-solid fa-screwdriver-wrench"></i></span><span class="hb-label">Tools</span><i class="fa-solid fa-chevron-right hb-go" aria-hidden="true"></i></a>
-- <a href="https://openvibe.games/game" style="--i:2" class="hb hb-game"><span class="hb-ico"><i class="fa-solid fa-gamepad"></i></span><span class="hb-label">Game</span><i class="fa-solid fa-chevron-right hb-go" aria-hidden="true"></i></a>
++ <a href="https://openvibe.games" style="--i:2" class="hb hb-game"><span class="hb-ico"><i class="fa-solid fa-gamepad"></i></span><span class="hb-label">Game</span><i class="fa-solid fa-chevron-right hb-go" aria-hidden="true"></i></a>
<a href="https://github.com/OpenVibers/OpenVibe.Live" target="_blank" style="--i:3" class="hb hb-github" rel="noopener"><span class="hb-ico"><i class="fa-brands fa-github"></i></span><span class="hb-label">GitHub</span><i class="fa-solid fa-chevron-right hb-go" aria-hidden="true"></i></a>
<a href="https://discord.gg/M6MuRUaeJj" target="_blank" style="--i:4" class="hb hb-discord" rel="noopener noreferrer"><span class="hb-ico"><i class="fa-brands fa-discord"></i></span><span class="hb-label">Discord</span><i class="fa-solid fa-chevron-right hb-go" aria-hidden="true"></i></a>
<a href="/documentation" onclick="return handleLinkClick(event, '/documentation')" style="--i:5" class="hb hb-vibe"
@@@ -505,20 +505,6 @@
</div>
<div class="container">
-- <!-- Scraplandia Leaderboards -->
-- <div class="section-header" style="--sc:#fbbf24;display:none" id="home-quest-header">
-- <h2><i class="fa-solid fa-trophy"></i> Scraplandia Leaderboards<small class="section-kicker">the ladder</small></h2>
-- <a href="https://openvibe.games/game" class="section-action">Play game</a>
-- </div>
-- <div class="home-leaderboards" id="home-leaderboards"></div>
--
-- <!-- Canvas Preview -->
-- <div class="section-header" style="--sc:#4ade80;display:none" id="home-canvas-header">
-- <h2><i class="fa-solid fa-palette"></i> Community Canvas<small class="section-kicker">drawn together</small></h2>
-- <a href="https://openvibe.games/canvas" class="section-action">Open canvas</a>
-- </div>
-- <div class="home-canvas-preview" id="home-canvas-preview"></div>
--
<div class="network-hub">
<div class="network-hub-header">
<i class="fa-solid fa-network-wired"></i>
@@@ -560,14 +546,6 @@
</div>
<i class="fa-solid fa-arrow-right network-card-arrow"></i>
</a>
-- <a href="https://openvibe.games/canvas" class="network-card">
-- <div class="network-card-icon" style="--card-accent:#3498db"><i class="fa-solid fa-palette"></i></div>
-- <div class="network-card-info">
-- <strong>Canvas</strong>
-- <span>Collaborative pixel art</span>
-- </div>
-- <i class="fa-solid fa-arrow-right network-card-arrow"></i>
-- </a>
<a href="https://openvibe.media" class="network-card">
<div class="network-card-icon" style="--card-accent:#f59e0b"><i class="fa-solid fa-photo-film"></i></div>
<div class="network-card-info">
@@@ -730,8 +708,6 @@
<!-- (page-themes removed: /themes redirects to openvibe.network in routeFromURL, so this
section was unreachable markup with five dead inline handlers.) -->
--<!-- Game & Canvas migrated to openvibe.games -->
--
<!-- ═══════════════════════════════════════════════════════════ -->
<!-- UPDATES / CHANGELOG -->
<!-- ═══════════════════════════════════════════════════════════ -->
ddiff --git a/public/js/app-home.js b/public/js/app-home.js
iindex bd9bf0e8..f2d4c8dd 100644
---- a/public/js/app-home.js
++++ b/public/js/app-home.js
@@@ -1248,10 +1248,6 @@ async function loadHome() {
loadHomeClips();
// Load recent pastes
loadHomePastes();
-- // Load Scraplandia leaderboards
-- loadHomeLeaderboards();
-- // Load Canvas preview
-- loadHomeCanvas();
startHomeRefresh(); // live grid + sections auto-update in real time
}
@@@ -1555,129 +1551,6 @@ async function loadHomePastes(opts) {
} catch { rail.filling = false; }
}
--// OpenVibe.Games does not serve /api/game/leaderboard/* or /api/game/canvas/state (the pixel canvas is
--// owner decision O15), so every first visit logged CORS errors for sections that stay hidden. Turn this
--// on when Games serves them (public, CORS for first-party origins) — roadmap WS-M task 7.
--const GAMES_HOME_WIDGETS = false;
--
--async function loadHomeLeaderboards() {
-- if (!GAMES_HOME_WIDGETS) { const h = document.getElementById('home-quest-header'); if (h) h.style.display = 'none'; return; }
-- try {
-- const boards = ['total_level', 'combat', 'mining', 'fishing'];
-- const questUrl = getScraplandiaUrl();
-- // One probe first: if the service is not answering, the other three would fail the same way.
-- const first = await fetchServiceJson(`${questUrl}/api/game/leaderboard/${boards[0]}`);
-- const rest = first ? await Promise.all(boards.slice(1).map(b => fetchServiceJson(`${questUrl}/api/game/leaderboard/${b}`))) : [];
-- const results = [first, ...rest].map(r => r || { entries: [] });
-- while (results.length < boards.length) results.push({ entries: [] });
-- const header = document.getElementById('home-quest-header');
-- const container = document.getElementById('home-leaderboards');
-- const hasData = results.some(r => r.entries && r.entries.length);
-- if (!hasData) { if (header) header.style.display = 'none'; return; }
-- if (header) header.style.display = '';
--
-- const labels = { total_level: 'Total Level', combat: 'Combat', mining: 'Mining', fishing: 'Fishing' };
-- const icons = { total_level: 'fa-star', combat: 'fa-sword', mining: 'fa-gem', fishing: 'fa-fish' };
-- container.innerHTML = boards.map((board, i) => {
-- const entries = (results[i].entries || []).slice(0, 5);
-- if (!entries.length) return '';
-- return `
-- <div class="home-lb-card">
-- <div class="home-lb-title"><i class="fa-solid ${icons[board] || 'fa-trophy'}"></i> ${labels[board]}</div>
-- <div class="home-lb-entries">
-- ${entries.map((e, rank) => `
-- <div class="home-lb-row">
-- <span class="home-lb-rank">${rank + 1}</span>
-- <span class="home-lb-name">${esc(e.display_name || e.username || 'Unknown')}</span>
-- <span class="home-lb-score">${typeof e.score === 'number' ? e.score.toLocaleString() : e.score}</span>
-- </div>
-- `).join('')}
-- </div>
-- </div>`;
-- }).join('');
-- } catch { /* silent */ }
--}
--
--/**
-- * Fetch JSON from another OpenVibe service, remembering when it is not there.
-- *
-- * The home page asks OpenVibe.Games for leaderboards and canvas state. Those endpoints currently
-- * answer with the Games SPA's HTML and no CORS headers, so from openvibe.live all five requests
-- * fail — on every single home page view. Failing is fine; failing five times per visit forever is
-- * not. A miss is remembered for a few hours per browser, so the page stops asking a service that
-- * is not answering and starts again on its own once the window lapses. A response that is not
-- * JSON counts as a miss instead of throwing inside .json().
-- */
--const _XSVC_MISS_KEY = 'ov_xsvc_miss_v1';
--const _XSVC_MISS_MS = 6 * 60 * 60 * 1000;
--function _xsvcMisses() { try { return JSON.parse(localStorage.getItem(_XSVC_MISS_KEY) || '{}'); } catch { return {}; } }
--async function fetchServiceJson(url) {
-- // Keyed per URL, not per service prefix: one board that 404s must not switch off every other
-- // endpoint on the same service for six hours.
-- const misses = _xsvcMisses();
-- if (misses[url] && Date.now() - misses[url] < _XSVC_MISS_MS) return null;
-- const remember = () => { try { misses[url] = Date.now(); localStorage.setItem(_XSVC_MISS_KEY, JSON.stringify(misses)); } catch { /* */ } };
-- let r;
-- try { r = await fetch(url, { credentials: 'omit' }); }
-- catch { remember(); return null; } // network / CORS: the service is not answering
-- const type = r.headers.get('content-type') || '';
-- if (!/json/i.test(type)) { remember(); return null; } // an HTML page where an API should be
-- // A JSON error means the service is there and answered — do not remember it as absent.
-- if (!r.ok) return null;
-- try { return await r.json(); } catch { return null; }
--}
--
--async function loadHomeCanvas() {
-- if (!GAMES_HOME_WIDGETS) { const h = document.getElementById('home-canvas-header'); if (h) h.style.display = 'none'; return; }
-- try {
-- const header = document.getElementById('home-canvas-header');
-- const container = document.getElementById('home-canvas-preview');
-- const data = await fetchServiceJson(`${getScraplandiaUrl()}/api/game/canvas/state`);
-- if (!data || !data.board) { if (header) header.style.display = 'none'; return; }
-- if (header) header.style.display = '';
--
-- const tiles = data.tiles || [];
-- const recentActions = data.recent_actions || [];
-- const uniqueArtists = new Set(tiles.map(t => t.user_id).filter(Boolean)).size;
-- const width = data.board.width || 64;
-- const height = data.board.height || 64;
-- const palette = data.board.palette || ['#000000'];
--
-- // Render a mini canvas preview
-- const scale = 4;
-- container.innerHTML = `
-- <div class="home-canvas-wrap">
-- <canvas id="home-canvas-mini" width="${width * scale}" height="${height * scale}" style="image-rendering:pixelated;border-radius:var(--radius);border:1px solid var(--border);max-width:100%;"></canvas>
-- <div class="home-canvas-stats">
-- <div class="home-canvas-stat"><strong>${tiles.length.toLocaleString()}</strong> <span>pixels placed</span></div>
-- <div class="home-canvas-stat"><strong>${uniqueArtists.toLocaleString()}</strong> <span>artists</span></div>
-- <div class="home-canvas-stat"><strong>${width}×${height}</strong> <span>board size</span></div>
-- <div class="home-canvas-stat"><strong>${recentActions.length}</strong> <span>recent actions</span></div>
-- </div>
-- <a href="${getScraplandiaUrl()}/canvas" class="btn btn-outline" style="margin-top:12px;">
-- <i class="fa-solid fa-palette"></i> Open Canvas
-- </a>
-- </div>
-- `;
--
-- // Draw tiles on the mini canvas
-- const canvas = document.getElementById('home-canvas-mini');
-- if (canvas) {
-- const ctx = canvas.getContext('2d');
-- ctx.fillStyle = palette[0] || '#000';
-- ctx.fillRect(0, 0, width * scale, height * scale);
-- for (const tile of tiles) {
-- const color = palette[tile.color_index] || '#fff';
-- ctx.fillStyle = color;
-- ctx.fillRect(tile.x * scale, tile.y * scale, scale, scale);
-- }
-- }
-- } catch {
-- const header = document.getElementById('home-canvas-header');
-- if (header) header.style.display = 'none';
-- }
--}
--
// Markup for a single stream card (live or recent). Extracted so the home page
// can reconcile the live grid in place for real-time updates.
function streamCardHTML(s, isLive) {
@@@ -1928,7 +1801,6 @@ function refreshHomeSections() {
if (untouched('vods') && typeof loadHomeRecentVods === 'function') loadHomeRecentVods();
if (untouched('clips') && typeof loadHomeClips === 'function') loadHomeClips();
if (untouched('pastes') && typeof loadHomePastes === 'function') loadHomePastes();
-- if (typeof loadHomeLeaderboards === 'function') loadHomeLeaderboards();
}
// The live grid follows OpenVibe.Events realtime (public/js/ov-live-realtime.js): a stream that
ddiff --git a/public/js/app.js b/public/js/app.js
iindex 89d350ce..5575e6f3 100644
---- a/public/js/app.js
++++ b/public/js/app.js
@@@ -17,7 +17,6 @@ function getDefaultOpenVibeNetworkUrls() {
const isTopenvibeAlias = ['topenvibe.tools', 'topenvibe.live', 'topenvibe.quest'].includes(host);
return {
tools: isLocalHost ? 'http://localhost:3100' : (isTopenvibeAlias ? 'https://topenvibe.tools' : 'https://openvibe.network'),
-- quest: isLocalHost ? 'http://localhost:3200' : (isTopenvibeAlias ? 'https://topenvibe.quest' : 'https://openvibe.games'),
};
}
@@@ -29,10 +28,6 @@ function getOpenVibeNetworkUrl(service) {
function getOpenVibeToolsUrl() {
return getOpenVibeNetworkUrl('tools');
}
--
--function getScraplandiaUrl() {
-- return getOpenVibeNetworkUrl('quest');
--}
/** Cached external viewer count (Kick/Twitch/RS) — updated by cumulative viewer poll */
let _cachedExternalViewerCount = 0;
@@@ -587,7 +582,7 @@ function _ssoHint() {
// What the signed-in account watches/opens here shows up in its network-wide History and the
// "Recently used" rows of the shared navbar on every other site. Recorded after the route
// rendered and its title settled; never for guests, and only for the pages worth remembering.
--const _HISTORY_PAGES = { channel: 'stream', 'vod-player': 'vod', 'clip-player': 'clip', 'paste-viewer': 'paste', pastes: null, game: 'game', arena: 'page' };
++const _HISTORY_PAGES = { channel: 'stream', 'vod-player': 'vod', 'clip-player': 'clip', 'paste-viewer': 'paste', pastes: null, arena: 'page' };
let _historyTimer = null;
function _recordHistory(pageId) {
const type = _HISTORY_PAGES[pageId];
@@@ -749,9 +744,6 @@ function onAuthChange() {
if (window.LiveNav) window.LiveNav.sync(currentUser || null);
if (currentUser) loadBalance();
-- // Sync canvas auth state if canvas page is loaded
-- if (typeof syncCanvasAuthState === 'function') syncCanvasAuthState();
--
try {
window.dispatchEvent(new CustomEvent('openvibe-auth-changed', {
detail: {
@@@ -1108,12 +1100,6 @@ function routeFromURL() {
} else if (segments[0] === 'chat') {
showPage('chat');
whenRouteReady('chat', () => loadChatPage());
-- } else if (segments[0] === 'game') {
-- window.location.href = `${getScraplandiaUrl()}/game`;
-- return;
-- } else if (segments[0] === 'canvas') {
-- window.location.href = `${getScraplandiaUrl()}/canvas`;
-- return;
} else if (segments[0] === 'pastes') {
// The Content feed's Pastes filter; ?edit=<slug> (from a paste's Edit button) opens the editor over it.
showPage('content');
@@@ -1294,20 +1280,15 @@ function showPage(page) {
// of each attaching MutationObservers to every section's class attribute.
try { document.dispatchEvent(new CustomEvent('ov:page', { detail: { page, changed } })); } catch { /* */ }
-- // Game/Canvas: hide footer only, keep navbar visible; other pages restore both
++ // Nothing hides the footer or blocks scrolling any more; a page that once did has to undo it.
const navbar = document.querySelector('.navbar');
const footer = document.querySelector('.footer');
-- if (page === 'game' || page === 'canvas') {
-- if (footer) footer.style.display = 'none';
-- document.body.style.overflow = 'hidden';
-- } else {
-- if (navbar) navbar.style.display = '';
-- if (footer) footer.style.display = '';
-- document.body.style.overflow = '';
-- }
++ if (navbar) navbar.style.display = '';
++ if (footer) footer.style.display = '';
++ document.body.style.overflow = '';
// Highlight nav link
-- const pageToNav = { home: 'home', content: 'content', moments: 'moments', search: 'search', broadcast: 'broadcast', dashboard: 'dashboard', admin: 'admin', chat: 'chat', game: 'game', canvas: 'game', 'paste-viewer': 'content', arena: 'arena' };
++ const pageToNav = { home: 'home', content: 'content', moments: 'moments', search: 'search', broadcast: 'broadcast', dashboard: 'dashboard', admin: 'admin', chat: 'chat', 'paste-viewer': 'content', arena: 'arena' };
const navPage = pageToNav[page];
if (navPage) {
const link = document.querySelector(`.nav-link[data-page="${navPage}"]`);
ddiff --git a/public/js/footer-live.js b/public/js/footer-live.js
iindex 8f0f6fdd..f99ae940 100644
---- a/public/js/footer-live.js
++++ b/public/js/footer-live.js
@@@ -11,7 +11,7 @@
*/
(function () {
'use strict';
-- const COMPACT_PAGES = ['channel', 'vod-player', 'clip-player', 'broadcast', 'game', 'canvas', 'chat', 'arena', 'recap'];
++ const COMPACT_PAGES = ['channel', 'vod-player', 'clip-player', 'broadcast', 'chat', 'arena', 'recap'];
const LINKS = [
{
heading: 'Watch',
ddiff --git a/public/js/ov-navbar-live.js b/public/js/ov-navbar-live.js
iindex 5e2c17d1..a7c0ab3e 100644
---- a/public/js/ov-navbar-live.js
++++ b/public/js/ov-navbar-live.js
@@@ -26,7 +26,7 @@
{ id: 'search', page: 'search', label: 'Search', href: '/search', icon: 'fa-magnifying-glass' },
{ id: 'chat', page: 'chat', label: 'Chat', href: '/chat', icon: 'fa-comments' },
{ id: 'arena', page: 'arena', label: 'Arena', href: '/arena', icon: 'fa-hand-fist' },
-- { id: 'game', page: 'game', label: 'Game', href: 'https://openvibe.games', icon: 'fa-gamepad' },
++ { id: 'game', label: 'Game', href: 'https://openvibe.games', icon: 'fa-gamepad' },
{ id: 'broadcast', page: 'broadcast', elId: 'nav-broadcast', label: 'Go Live', href: '/broadcast', icon: 'fa-tower-broadcast', dot: false, dotId: 'nav-live-dot',
onClick: (e) => call('goLiveNav', e),
children: user ? [{ id: 'dashboard', label: 'Dashboard', href: '/dashboard', icon: 'fa-gauge-high', onClick: (e) => call('dashNav', e) }] : [] },
ddiff --git a/server/index.js b/server/index.js
iindex 8da5694a..453e99b9 100644
---- a/server/index.js
++++ b/server/index.js
@@@ -143,8 +143,6 @@ const analyticsModule = require('openvibe-shared/analytics'); // ADR-021: no IP/
// WHIP (WebRTC-HTTP Ingestion Protocol)
const whipHandler = require('./streaming/whip-handler');
--// Game & Canvas — migrated to openvibe.games (game/canvas code removed)
--
// ── Express App ──────────────────────────────────────────────
const app = express();
const server = http.createServer(app);
@@@ -715,10 +713,6 @@ app.use('/api/emotes', emoteRoutes);
app.use('/api/sounds', chatRemote ? chatMoved : require('./chat/sounds-routes'));
app.use('/api/ai-viewers', require('./ai/viewers/routes'));
app.use('/api/powerchat', require('./integrations/powerchat-routes'));
--// Game & Canvas — migrated to openvibe.games
--app.get('/game', (req, res) => res.redirect(301, 'https://openvibe.games/game'));
--app.get('/canvas', (req, res) => res.redirect(301, 'https://openvibe.games/canvas'));
--app.use('/api/game', (req, res) => res.status(410).json({ error: 'Game has moved to https://openvibe.games/game' }));
app.use('/api/meta', metaRoutes);
app.use('/api/pastes', pasteRoutes);
app.use('/api/content', require('./content/routes')); // Content (people's work) + Moments (AI) feeds
@@@ -1107,8 +1101,6 @@ server.on('upgrade', (req, socket, head) => {
controlServer.handleUpgrade(req, socket, head);
} else if (url.startsWith('/ws/call')) {
callServer.handleUpgrade(req, socket, head);
-- } else if (url.startsWith('/ws/game') || url.startsWith('/ws/canvas')) {
-- socket.destroy(); // migrated to openvibe.games
} else if (url.startsWith('/ws/robotstreamer-publish')) {
robotStreamerService.handleUpgrade(req, socket, head);
} else {
@@@ -1182,8 +1174,6 @@ async function start() {
console.log(`[Server] Admin user "${adminUser}" created from ADMIN_USERNAME; sign in with the openvibe.network account of that name`);
}
-- // Game & Canvas migrated to openvibe.games — no local init needed
--
// 3. Initialize chat server
chatServer.init(server);
vibeCodingPublishServer.init(server);
@@@ -1199,8 +1189,6 @@ async function start() {
// 4b. Initialize broadcast server
broadcastServer.init(server);
-- // Game & Canvas WebSocket servers migrated to openvibe.games
--
// 4d. Initialize group call signaling server
callServer.init(server);
if (require('./streaming/calls-authority').isChat()) {
@@@ -1329,7 +1317,6 @@ async function start() {
console.log(`[Server] WebSocket: ws://${config.host}:${config.port}/ws/broadcast`);
console.log(`[Server] WebSocket: ws://${config.host}:${config.port}/ws/control`);
console.log(`[Server] WebSocket: ws://${config.host}:${config.port}/ws/call`);
-- console.log(`[Server] Game/Canvas: migrated to openvibe.games`);
console.log(`[Server] Environment: ${config.nodeEnv}`);
console.log(`[Server] BASE_URL: ${config.baseUrl}`);
console.log(`[Server] WHIP_PUBLIC_URL: ${config.whip?.publicUrl}`);
@@@ -1676,7 +1663,6 @@ function shutdown() {
restreamManager.stopViewerCountPolling();
restreamManager.stopAll();
try { recorder.stopAll(); } catch {}
-- // canvasServer + gameServer migrated to openvibe.games
callServer.close();
chatServer.close();
controlServer.close();
ddiff --git a/setup-guide.html b/setup-guide.html
iindex d0542f36..e697e7da 100644
---- a/setup-guide.html
++++ b/setup-guide.html
@@@ -203,7 +203,7 @@ section.visible{opacity:1;transform:none}
<p>The current server in <code>server/index.js</code> provides:</p>
<ul>
<li>HTTP on <code>PORT</code>, default <code>3000</code></li>
--<li>WebSocket upgrades on <code>/ws/chat</code>, <code>/ws/broadcast</code>, <code>/ws/control</code>, <code>/ws/call</code>, and <code>/ws/game</code></li>
++<li>WebSocket upgrades on <code>/ws/chat</code>, <code>/ws/broadcast</code>, <code>/ws/control</code>, and <code>/ws/call</code></li>
<li>Optional RTMP ingest</li>
<li>Optional JSMPEG relay</li>
<li>Optional WebRTC / <code>mediasoup</code></li>
ddiff --git a/test/home-order.test.js b/test/home-order.test.js
iindex 73dd29f1..b9cb2810 100644
---- a/test/home-order.test.js
++++ b/test/home-order.test.js
@@@ -58,7 +58,7 @@ check('nothing was removed', () => {
for (const id of ['home-featured', 'stream-grid-live', 'home-digest', 'home-star-section', 'hero-egg', 'home-pulse-section',
'stream-grid-recent', 'stream-grid-recent-pagination', 'home-recent-vods-header', 'home-recent-vods-grid', 'home-clips-header',
'home-clips-grid', 'home-pastes-header', 'home-pastes-list', 'home-moments-section', 'home-tour-mount', 'home-cta-banner',
-- 'home-about-body', 'home-quest-header', 'home-leaderboards', 'home-canvas-header', 'home-canvas-preview']) {
++ 'home-about-body']) {
at(`id="${id}"`);
}
assert.ok(home.includes('class="network-hub"'));