openvibers/openvibe.wiki Commits

Wiki moves between its pages without a reload (plan T11): openvibe-shared v2.2.0 boost swaps <main> styles-first with the shared transition, prefetching on intent, and does a normal load across a deploy (the ov-boost marker carries the release). The navbar's sign-in returns to the current page. Tests pin the marker, the boost tag and the login template (verified).

OP OpenVibers committed 29 Sept 2026 · f36c94290f · 7 files, +21 −9


Changes

ddiff --git a/README.md b/README.md
iindex edc5887..6822eb9 100644
---- a/README.md
++++ b/README.md
@@@ -272,7 +272,7 @@ Production: `/opt/openvibe.wiki`, env `/etc/openvibe/wiki.env`, unit
- PostgreSQL 18 and Valkey 9 (OpenVibe.Host `roles/data/`, ADR-035): every read and write is async through
`openvibe-sdk/db`; Valkey holds the per-actor limit counters (optional: without `VALKEY_URL` they count per process).
--- `openvibe-publishing` v1.0.0 (async PostgreSQL stores), `openvibe-contracts` v0.76.0, `openvibe-shared` v1.27.0
++- `openvibe-publishing` v1.0.0 (async PostgreSQL stores), `openvibe-contracts` v0.76.0, `openvibe-shared` v2.2.0
(Frame, release, metrics, readiness, SEO helpers, legal pages), `openvibe-sdk` v0.19.0 (db, auth, PostgreSQL
events outbox, per-actor limits, testing) — pinned release tarballs.
- OpenVibe.Network (SSO, JWKS, service principal `wiki`), OpenVibe.Events, OpenVibe.Community,
ddiff --git a/STATUS.json b/STATUS.json
iindex 62a2252..097374f 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -10,7 +10,7 @@
"contracts": "openvibe-contracts v0.76.0",
"packages": [
"openvibe-publishing v1.0.0",
-- "openvibe-shared v1.27.0",
++ "openvibe-shared v2.2.0",
"openvibe-sdk v0.19.0"
],
"capabilities": [
ddiff --git a/package-lock.json b/package-lock.json
iindex 6af26f5..4085e27 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -17,7 +17,7 @@
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.76.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.0.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.19.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.29.2",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.2.0",
"pg": "^8.23.0"
},
"devDependencies": {
@@@ -1196,9 +1196,9 @@
}
},
"node_modules/openvibe-shared": {
-- "version": "1.29.2",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.29.2",
-- "integrity": "sha512-w5daRSzujokYT1/Q3fu0KdcSZUBEv1pm66H8vIAI2SY0xtOaLqgfkXJpfIz1NgvJuyK8dhXBbLjM8Ow9RZ5x+A==",
++ "version": "2.2.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.2.0",
++ "integrity": "sha512-1q+iUuUxzPeylTYmithW4jR++Jccvn5GEOrB1B3D18Dgn6OXQhPpvhPQAa1D1k1p+dWIa1/SmggyJwSGFnTNtw==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0"
ddiff --git a/package.json b/package.json
iindex 3e36f6f..a0c6266 100644
---- a/package.json
++++ b/package.json
@@@ -28,7 +28,7 @@
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.76.0",
"openvibe-publishing": "https://codeload.github.com/OpenVibers/OpenVibe.Publishing/tar.gz/refs/tags/v1.0.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.19.0",
-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.29.2",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.2.0",
"pg": "^8.23.0"
},
"engines": {
ddiff --git a/server/app.js b/server/app.js
iindex a401de5..2a0b2e6 100644
---- a/server/app.js
++++ b/server/app.js
@@@ -32,6 +32,7 @@ function createApp({ config, svc, viewers: baseViewers, platform, keys, db, valk
require('openvibe-shared/trace').install(app);
const release = require('openvibe-shared/release').createRelease({ service: 'wiki', root: path.join(__dirname, '..') });
++ require('./render/layout').setRelease(release.release);
const metrics = require('openvibe-shared/metrics').instrument(app, { service: 'wiki', release: release.release });
metrics.registry.gauge({
name: 'wiki_event_outbox', help: 'Events in the outbox by state', labelNames: ['state'],
ddiff --git a/server/render/layout.js b/server/render/layout.js
iindex 3df44fd..153186d 100644
---- a/server/render/layout.js
++++ b/server/render/layout.js
@@@ -32,6 +32,11 @@ function asset(rel) {
/** The ?v= this process renders for a public/ file (the static route caches only that one as immutable). */
function assetVersion(rel) { asset(rel); return hashes.get(rel); }
++// The deployed release (app.js sets it from openvibe-shared/release): openvibe-shared/boost swaps a page in place only
++// between pages of the same release, and does a normal load across a deploy.
++let RELEASE = 'dev';
++function setRelease(id) { if (id) RELEASE = String(id); }
++
function navConfig(o, config) {
return {
service: 'wiki',
@@@ -44,7 +49,7 @@ function navConfig(o, config) {
history: { type: 'page', title: o.title || SITE_NAME },
silentLogin: `${config.baseUrl}/auth/login?silent=1&next={url}`,
sessionUrl: '/auth/me',
-- loginUrl: `/auth/login?next=${encodeURIComponent(o.path || '/')}`,
++ loginUrl: '/auth/login?next={path}', // filled from the current page (boost moves between pages)
logoutUrl: '/auth/logout?next={path}', // Sign out in the shared navbar ends this site's session too
notificationsRealtime: true, // the bell hears new notifications over OpenVibe.Events (Shared 1.22.0)
};
@@@ -82,6 +87,8 @@ ${feeds.map((f) => `<link rel="alternate" type="${f.type}" title="${esc(f.title)
<script src="${ovServe.url('theme-loader.js')}" defer></script>
<script src="${ovServe.url('navbar.js')}" defer></script>
<script src="${ovServe.url('footer.js')}" defer></script>
++<meta name="ov-boost" content="wiki@${esc(RELEASE)}">
++<script src="${ovServe.url('boost.js')}" data-main="#main" defer></script>
</head>
<body>
<a class="wk-skip" href="#main">Skip to content</a>
@@@ -103,4 +110,4 @@ document.addEventListener('DOMContentLoaded', function () {
</html>`;
}
--module.exports = { renderPage, asset, SITE_NAME, DEFAULT_DESCRIPTION, NETWORK_URL, assetVersion };
++module.exports = { renderPage, asset, setRelease, SITE_NAME, DEFAULT_DESCRIPTION, NETWORK_URL, assetVersion };
ddiff --git a/test/shipped-pages.test.js b/test/shipped-pages.test.js
iindex a52057f..1596daa 100644
---- a/test/shipped-pages.test.js
++++ b/test/shipped-pages.test.js
@@@ -13,6 +13,10 @@ const H = require('./helpers');
assert.strictEqual(r.status, 200);
assert.ok(r.text.includes('data-ov-shipped="latest" data-service="wiki" href="/updates"'));
assert.ok(r.text.includes('"logoutUrl":"/auth/logout?next={path}"'));
++ assert.ok(r.text.includes('"loginUrl":"/auth/login?next={path}"'), 'the navbar sign-in returns to the current page (boost swaps it in place)');
++ assert.ok(/<meta name="ov-boost" content="wiki@[^"]+">/.test(r.text), 'the boost marker carries the release');
++ assert.ok(r.text.includes('<script src="/shared/boost.js?v=') && r.text.includes('data-main="#main"'), 'the boost script swaps #main');
++ assert.ok(r.text.includes('<main id="main"'), 'the boost marker targets an existing main');
assert.ok(/<noscript><span class="wk-account">/.test(r.text), 'the site account strip only without JavaScript');
assert.ok(r.text.includes('"updates":"/updates"'));
r = await H.req(h, 'GET', '/updates');