openvibers/openvibe.live Commits

openvibe-shared v4.64.0 (was v4.62.0) (#482)

OP OpenVibers committed 13 days ago · f745fd5421 · 8 files, +48 −21

* openvibe-shared v4.64.0 (was v4.62.0)

Opened by scripts/pin-bump.js in OpenVibers/OpenVibe.Shared after the v4.64.0 release.

* Paint the look with openvibe-shared's look-boot before first paint (L42)

Live's own bootstrap painted only ov_theme, so a season turned off elsewhere stayed on, and orange, until the deferred
loader caught up. look-boot paints the look this browser last painted here, or the one a link from another OpenVibe
page carried, with the display settings. A browser with only ov_theme is painted from it once.

* Perf budget for openvibe-shared 4.64.0: the look travels between sites, the Look panel

Raised to the size this PR's CI measured (jsRawKB 1243.5 > 1243), with a dated note.

Changes

ddiff --git a/README.md b/README.md
iindex 9a5775e9..f1fa11b6 100644
---- a/README.md
++++ b/README.md
@@@ -177,5 +177,5 @@ Minimum `.env`: `BASE_URL`, `JWT_SECRET`, `OV_NETWORK_URL`, `OV_NETWORK_INTERNAL
<!-- versions:start -->
- openvibe-contracts: v0.222.0
- openvibe-sdk: v0.74.0
--- openvibe-shared: v4.62.0
++- openvibe-shared: v4.64.0
<!-- versions:end -->
ddiff --git a/STATUS.json b/STATUS.json
iindex be494bdb..52ceeecc 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -7,7 +7,7 @@
"domain": "openvibe.live (www, ingest, whip)",
"contracts": "openvibe-contracts v0.222.0",
"sdk": "openvibe-sdk v0.74.0",
-- "shared": "openvibe-shared v4.62.0",
++ "shared": "openvibe-shared v4.64.0",
"capabilities": [
"live.chat_context.read",
"live.chat_effects.write",
ddiff --git a/package-lock.json b/package-lock.json
iindex 7cb8c85c..19556a2c 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -25,7 +25,7 @@
"onnxruntime-node": "^1.20.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.62.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.64.0",
"pg": "^8.23.1",
"sanitize-html": "^2.17.7",
"sdp-transform": "^3.0.0",
@@@ -2884,9 +2884,9 @@
}
},
"node_modules/openvibe-shared": {
-- "version": "4.62.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.62.0",
-- "integrity": "sha512-JlFI7rOngOwpRC3lZXRkKsOv4CM5boPJqhm7URMVXq9VMMczyf9FdOw9tn3017pzquMVYYc3fz63v1B1mhSxsw==",
++ "version": "4.64.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.64.0",
++ "integrity": "sha512-oQwj8SpCqVzVMyeX5ayXvL0LtYi4355f1s7OB99RpxIxGU9ITYVnTJraXGWJtHor1mHCiLWeOiyR0Z5pee5apQ==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0",
ddiff --git a/package.json b/package.json
iindex 9e516b43..f74538ed 100644
---- a/package.json
++++ b/package.json
@@@ -44,7 +44,7 @@
"onnxruntime-node": "^1.20.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.74.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.62.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.64.0",
"pg": "^8.23.1",
"sanitize-html": "^2.17.7",
"sdp-transform": "^3.0.0",
ddiff --git a/public/index.html b/public/index.html
iindex a136ee69..9933adc1 100644
---- a/public/index.html
++++ b/public/index.html
@@@ -39,23 +39,21 @@
<link rel="apple-touch-icon" href="/assets/logo-192.png">
<link rel="apple-touch-icon" href="/assets/logo-192.png">
-- <!-- Critical theme bootstrap (ov-theme-boot) — MUST stay inline and stay ABOVE the stylesheets.
-- Paints the user's cached theme synchronously, before the browser has any chance to
-- render the default palette. theme-loader.js used to be the first thing to touch the
-- theme, but it is fetched over the network and loaded with defer, so it ran after the
-- page had already painted — that gap is the purple flash. This reads localStorage
-- only: no network, no parse blocking, works offline and on the very first paint. -->
++ <!-- The look before first paint (ov-theme-boot): MUST stay ABOVE the stylesheets. server/web/assets.js puts
++ openvibe-shared's look-boot here: it paints the look this browser last painted on Live, or the one a link from
++ another OpenVibe page carried, with the display settings (seasonal off, Calm, text size). theme-loader.js loads
++ with defer, so without it the default palette (or an old season) showed first. localStorage only, no network. -->
++ <!--ov:look-boot-->
<script>
++ // A browser from before look-boot has only its theme (ov_theme), not yet a painted look (ov_paint): paint that once.
(function () {
try {
-- var raw = localStorage.getItem('ov_theme');
-- if (!raw) return;
-- var t = JSON.parse(raw), v = t && t.variables;
++ if (localStorage.getItem('ov_paint')) return;
++ var t = JSON.parse(localStorage.getItem('ov_theme') || 'null'), v = t && t.variables, el = document.documentElement;
if (!v) return;
-- var el = document.documentElement;
-- for (var k in v) if (k.charAt(0) === '-') el.style.setProperty(k, v[k]);
-- if (t.id) el.setAttribute('data-theme', t.id);
-- } catch (_) { /* cold cache or private mode — theme-loader.js resolves it shortly */ }
++ for (var k in v) if (k.charAt(0) === '-' && /^[#0-9a-z(),.%\s-]{1,80}$/i.test(String(v[k])) && !/url|expression/i.test(String(v[k]))) el.style.setProperty(k, v[k]);
++ if (t.id && /^[a-z0-9-]{1,40}$/.test(t.id)) el.setAttribute('data-theme', t.id);
++ } catch (_) { /* nothing kept: theme-loader.js paints shortly */ }
})();
// "Lite" rendering for phones, coarse pointers and low-memory devices. Stylesheets on every
// route key off .rs-lite, so it is decided here, before first paint, rather than by the home
ddiff --git a/scripts/perf/check-budgets.js b/scripts/perf/check-budgets.js
iindex 8fa900c9..22b11060 100644
---- a/scripts/perf/check-budgets.js
++++ b/scripts/perf/check-budgets.js
@@@ -22,7 +22,7 @@ const BUDGETS = {
htmlRawKB: 120, // measured 94.9
htmlBrotliKB: 30,
jsFiles: 26, // measured 23 (incl. route scripts for "/")
-- jsRawKB: 1243, // 1242.7 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face, and the ring on page moves (2026-10-31); 1238.8 with the home's featured stream once and the intro closed on phones (2026-10-31); 1237.4 with the home's two more tab blocks on phones (2026-10-30); 1233.9 with the home's Catch up tabs on phones (2026-10-30); 1230.8 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 1227.8 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 1223.5 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 1215.4 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); measured 1203.9 (2026-10-28: openvibe-shared 4.30.0, the bell center: tabs with counts, the Unread filter, thumbnails, swipe, the phone sheet; 4.31.0's ✦ adds about 3 KB); 1187.2 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0: opaque themed toasts held while a menu is open, grouping, priority, System cards and the rich bell panel); 1158.8 (2026-10-28: openvibe-shared 4.25.0, the menu's orb, messages, the phone sheet and auto-hide in the navbar; the messenger opens from the bar)
++ jsRawKB: 1244, // 1243.5 with openvibe-shared 4.64.0: the look travels between sites, the Look panel in the menu (2026-10-31); 1242.7 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face, and the ring on page moves (2026-10-31); 1238.8 with the home's featured stream once and the intro closed on phones (2026-10-31); 1237.4 with the home's two more tab blocks on phones (2026-10-30); 1233.9 with the home's Catch up tabs on phones (2026-10-30); 1230.8 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 1227.8 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 1223.5 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 1215.4 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); measured 1203.9 (2026-10-28: openvibe-shared 4.30.0, the bell center: tabs with counts, the Unread filter, thumbnails, swipe, the phone sheet; 4.31.0's ✦ adds about 3 KB); 1187.2 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0: opaque themed toasts held while a menu is open, grouping, priority, System cards and the rich bell panel); 1158.8 (2026-10-28: openvibe-shared 4.25.0, the menu's orb, messages, the phone sheet and auto-hide in the navbar; the messenger opens from the bar)
jsBrotliKB: 292, // 291.1 with openvibe-shared 4.57.1 (the Dock's async token and scope-aware controls, 4.57.0; the tool frame's facts, 4.56.0) (2026-10-31); 290.6 with the home's two more tab blocks on phones (2026-10-30); 289.8 with the home's Catch up tabs on phones (2026-10-30); 288.2 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 287.4 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); measured 283.2 (2026-10-28: openvibe-shared 4.30.0, the bell center as above); 279.6 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0 as above); 273.1 (2026-10-28: openvibe-shared 4.25.0 as above); 270.5 (2026-10-28: openvibe-shared 4.22.0, the navbar's search magnifier with / and Ctrl+K and the More menu; search.js and loading.js load only when used); 269.6 (2026-10-28: openvibe-shared 4.19.0, the account menu's gear and people-group icons inline; 268 on 2026-10-27: openvibe-shared 4.16.0, the folded balance chip, Across OpenVibe with site marks and the icon preload in the navbar); 265.3 (2026-10-27: openvibe-shared 4.15.0, the compact footer opens into the whole one, and the pulse line); 263.3 on 10-23 (openvibe-shared 4.9.0, status text twins in every theme); 262.5 on 10-17 (openvibe-shared 4.4.0, every site in the launcher)
cssRawKB: 270, // measured ~243 since the first-paint subset (style.core.css) replaced style.css (~717 before)
cssBrotliKB: 55, // measured ~47.5 (was ~130)
ddiff --git a/server/web/assets.js b/server/web/assets.js
iindex d6a7f5d4..0b7a08c1 100644
---- a/server/web/assets.js
++++ b/server/web/assets.js
@@@ -38,6 +38,10 @@ const critical = require('./critical-css');
const CORE_CSS = '/css/style.core.css';
const REF_RE = /(["'])(\/(?:js|css|shared|fragments)\/[A-Za-z0-9_./-]+?\.(?:js|css|html))(?:\?v=[A-Za-z0-9_.-]*)?\1/g;
const MANIFEST_MARK = '<!--ov:asset-manifest-->';
++// The look before first paint (openvibe-shared look-boot, plan L42): this browser's last painted look on this site, or
++// the one a link from another OpenVibe page carried, with the display settings (the season switch among them).
++const LOOK_BOOT_MARK = '<!--ov:look-boot-->';
++const { BOOT: LOOK_BOOT } = require('openvibe-shared/look-boot');
const ROUTE_CSS_MARK = '<!--ov:route-css-->';
const ROUTE_JS_MARK = '<!--ov:route-js-->';
const FEATURES_PATH = path.join(PUBLIC_DIR, 'features.json');
@@@ -240,6 +244,7 @@ function rewriteHtml(html) {
const h = hashOf(urlPath);
return h ? `${q}${urlPath}?v=${h}${q}` : m;
});
++ if (out.includes(LOOK_BOOT_MARK)) out = out.replace(LOOK_BOOT_MARK, () => `<script>${LOOK_BOOT}</script>`);
if (out.includes(MANIFEST_MARK)) {
const reg = features();
const payload = {
ddiff --git a/test/look-boot.test.js b/test/look-boot.test.js
nnew file mode 100644
iindex 00000000..bdba0d2f
---- /dev/null
++++ b/test/look-boot.test.js
@@@ -0,0 +1,24 @@
++'use strict';
++// The look before first paint (openvibe-shared 4.64.0 look-boot, plan L42; the owner, 10-31: seasonal turned off on
++// Network was still on, and orange, on Live). theme-loader.js loads with defer here, so the document's head carries
++// look-boot: the look this browser last painted on Live (ov_paint), or the one a link from another OpenVibe page just
++// carried (?ov_look=), with the display settings. It sits above every stylesheet, and the marker never reaches a page.
++const assert = require('assert');
++const assets = require('../server/web/assets');
++const { BOOT } = require('openvibe-shared/look-boot');
++
++const doc = assets.document('index.html').html;
++const at = doc.indexOf(BOOT);
++assert.ok(at > 0, 'the head carries look-boot');
++assert.ok(!doc.includes('<!--ov:look-boot-->'), 'the marker is replaced');
++const firstSheet = doc.search(/<link[^>]+rel="stylesheet"/);
++assert.ok(firstSheet > 0 && at < firstSheet, 'it paints before any stylesheet');
++assert.ok(at < doc.indexOf('/shared/theme-loader.js'), 'and before the loader');
++assert.strictEqual(doc.split(BOOT).length, 2, 'once');
++// A browser from before look-boot (ov_theme only) is painted once from its theme, colours only.
++const legacy = doc.slice(at, firstSheet);
++assert.match(legacy, /if \(localStorage\.getItem\('ov_paint'\)\) return;/);
++assert.match(legacy, /!\/url\|expression\/i\.test/);
++// Every route's document keeps it (renderRoute works on the same base).
++assert.ok(assets.renderRoute(doc, '/@someone').includes(BOOT), 'a channel page too');
++console.log('look boot: the head paints the kept or carried look before any stylesheet, once, on every route');