openvibers/openrestream Commits

The shared update system and one account UI, on the OpenVibe Frame (openvibe-shared 1.11.0, openvibe/frame): the home shows what shipped, /updates is the shared log and the footer links it; the shared navbar handles sign in and out (logoutUrl ends this site's session) and carries this site's account links in its menu, while the page's own account bar is only for no-JS visitors

OP OpenVibers committed 24 Sept 2026 · ea87a94432 · 4 files, +15 −10


Changes

ddiff --git a/package-lock.json b/package-lock.json
iindex c8a246d..69baac9 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -16,7 +16,7 @@
"node-media-server": "2.7.4",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.7.0"
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0"
},
"engines": {
"node": ">=22.12.0"
@@@ -1140,9 +1140,9 @@
}
},
"node_modules/openvibe-shared": {
-- "version": "1.7.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.7.0",
-- "integrity": "sha512-gF1PABMEGHhtu0WMkJQHwJOvbYzWcdfOi3feGYrCUkLXIZhpeSvrSOD7SF0+nveWhfCQMFjqNU8Q0d90vv4s/A==",
++ "version": "1.11.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0",
++ "integrity": "sha512-edMW0I25HNFReLcfZ9ak+4q5sy2t7qq7EPG52tOerTBV2fU994C5we/02AD/9i2Vuq0+ayNBBisW0cg60L6DLQ==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0"
ddiff --git a/package.json b/package.json
iindex 5d659fb..2795b6d 100644
---- a/package.json
++++ b/package.json
@@@ -25,7 +25,7 @@
"node-media-server": "2.7.4",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.5.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.7.0"
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.0"
},
"engines": {
"node": ">=22.12.0"
ddiff --git a/server/ui/layout.js b/server/ui/layout.js
iindex 3dda26b..97de849 100644
---- a/server/ui/layout.js
++++ b/server/ui/layout.js
@@@ -1,7 +1,7 @@
'use strict';
/**
* Page shell for openre.stream: server-rendered HTML that works without JavaScript, with the shared
-- * OpenVibe chrome (theme loader, navbar and footer from openvibe.network, footer SSR from the
++ * OpenVibe Frame (theme loader, navbar and footer from openvibe.network, footer SSR from the
* pinned openvibe-shared release) the way OpenVibe.Community renders it.
*/
const NETWORK_URL = 'https://openvibe.network';
@@@ -44,11 +44,12 @@ function renderPage({ title, body, user, canonicalPath = '/', robots = 'noindex,
],
sessionUrl: '/auth/me',
loginUrl: `/auth/login?next=${encodeURIComponent(canonicalPath)}`,
++ logoutUrl: '/auth/logout?next={path}', // Sign out in the shared navbar ends this site's session too
};
-- const foot = { service: 'openre', variant: 'compact', mount: '#ov-footer', brandName: SITE, legalBase: config.liveUrl,
++ const foot = { service: 'openre', variant: 'compact', mount: '#ov-footer', brandName: SITE, legalBase: config.liveUrl, updates: '/updates',
links: [{ heading: SITE, items: [{ name: 'Streams', url: '/streams' }, { name: 'Source code', url: 'https://github.com/OpenVibers/OpenRe.Stream' }] }] };
let footerSsr = '';
-- try { footerSsr = require('openvibe-shared/footer').ssr({ service: 'openre', variant: 'compact' }); } catch { footerSsr = '<footer id="ov-footer"></footer>'; }
++ try { footerSsr = require('openvibe-shared/footer').ssr({ service: 'openre', variant: 'compact', updates: '/updates' }); } catch { footerSsr = '<footer id="ov-footer"></footer>'; }
let icon = '';
try { icon = require('openvibe-shared/app-icon').headTags({ site: 'network' }); } catch { icon = ''; }
return `<!DOCTYPE html>
@@@ -76,7 +77,7 @@ ${footerSsr}
<script>
window.__OV_PAGE = ${JSON.stringify({ navbar: nav, footer: foot }).replace(/</g, '\\u003c')};
document.addEventListener('DOMContentLoaded', function () {
-- try { if (window.OpenVibeNavbar) OpenVibeNavbar.init(window.__OV_PAGE.navbar); } catch (e) { /* chrome is optional */ }
++ try { if (window.OpenVibeNavbar) OpenVibeNavbar.init(window.__OV_PAGE.navbar); } catch (e) { /* the Frame is optional */ }
try { if (window.OpenVibeFooter) OpenVibeFooter.init(window.__OV_PAGE.footer); } catch (e) { /* */ }
});
</script>
ddiff --git a/server/ui/routes.js b/server/ui/routes.js
iindex e158c24..0cdfb88 100644
---- a/server/ui/routes.js
++++ b/server/ui/routes.js
@@@ -14,6 +14,7 @@
* read the cookie, so it cannot produce the token); SameSite=Lax cookies are the second layer.
*/
const crypto = require('crypto');
++const frame = require('openvibe-shared/frame');
const express = require('express');
const { renderPage, esc } = require('./layout');
const { StoreError } = require('../store/definitions');
@@@ -79,6 +80,8 @@ function createUiRouter({ rt, auth }) {
// ── Pages ─────────────────────────────────────────────────
++ // What shipped on OpenRe.Stream: the shared update log every OpenVibe site has.
++ router.get('/updates', (req, res) => page(req, res, { canonicalPath: '/updates', robots: 'index,follow', title: 'What shipped on OpenRe.Stream', body: frame.updatesBody({ service: 'openre', siteName: 'OpenRe.Stream' }) + frame.shippedScript() }));
router.get('/', (req, res) => {
const signedIn = req.caller.kind === 'user' && req.caller.subject;
const mine = signedIn ? store.definitions.list({ owner_subject: req.caller.subject }) : [];
@@@ -87,7 +90,8 @@ function createUiRouter({ rt, auth }) {
body: `<h1>OpenRe.Stream</h1>
<p>Ingest and restream for the OpenVibe network: stream definitions with hashed ingest keys, RTMP ingest sessions that run in transport workers separate from any web deploy, restream outputs with health and logs, and recording requests to OpenVibe.Media.</p>
<p class="muted">Status: alpha. RTMP ingest and RTMP/SRT restreaming work here; WHIP, WebRTC/SFU and JSMPEG are still served by OpenVibe.Live. Channels, discovery and watch pages stay on <a href="${esc(config.liveUrl)}">openvibe.live</a>.</p>
--${signedIn ? `<h2>Your streams</h2>${mine.length ? streamTable(mine) : '<p class="muted">No streams yet.</p>'}<p><a href="/streams">Manage streams</a></p>` : '<p><a href="/auth/login?next=/streams">Sign in with OpenVibe</a> to manage your streams.</p>'}`,
++${signedIn ? `<h2>Your streams</h2>${mine.length ? streamTable(mine) : '<p class="muted">No streams yet.</p>'}<p><a href="/streams">Manage streams</a></p>` : '<p><a href="/auth/login?next=/streams">Sign in with OpenVibe</a> to manage your streams.</p>'}
++${frame.shipped({ service: 'openre', title: 'Recently shipped on OpenRe.Stream' })}`,
});
});