openvibers/openvibe.wiki Commits

The Wiki home opens with what OpenVibe.Wiki is for (plan T11, D92; openvibe-shared v2.3.1 showcase): 'Knowledge, with sources', where to start (start a space, or sign in to), and the six things a space gets today (page trees, revision history, citations, Community discussion, roles and visibility, search and feeds); the spaces and recent pages follow. The kit's stylesheet is linked on the home only. Home budgets raised as a decision (html 27.5 KB, css 18 KB). Suites green.

OP OpenVibers committed 29 Sept 2026 · c6e6f4de0f · 9 files, +42 −15


Changes

ddiff --git a/README.md b/README.md
iindex dba913c..4cef08b 100644
---- a/README.md
++++ b/README.md
@@@ -278,7 +278,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` v2.2.0
++- `openvibe-publishing` v1.0.0 (async PostgreSQL stores), `openvibe-contracts` v0.76.0, `openvibe-shared` v2.3.1
(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 097374f..3181236 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 v2.2.0",
++ "openvibe-shared v2.3.1",
"openvibe-sdk v0.19.0"
],
"capabilities": [
ddiff --git a/package-lock.json b/package-lock.json
iindex 4085e27..4645ed9 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/v2.2.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.3.1",
"pg": "^8.23.0"
},
"devDependencies": {
@@@ -1196,9 +1196,9 @@
}
},
"node_modules/openvibe-shared": {
-- "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==",
++ "version": "2.3.1",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.3.1",
++ "integrity": "sha512-K+MXnB4O+8xIFi+NQGC2SDTvDq3RkzfxQ3bTVx76Y/Rbuq7kC/L5kL3c/06xr9sPYcjyzF3Bhpv5yH2YNfR4Zw==",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0"
ddiff --git a/package.json b/package.json
iindex a0c6266..41ba39d 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/v2.2.0",
++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v2.3.1",
"pg": "^8.23.0"
},
"engines": {
ddiff --git a/public/css/wiki.css b/public/css/wiki.css
iindex 8b53a09..c07a212 100644
---- a/public/css/wiki.css
++++ b/public/css/wiki.css
@@@ -72,3 +72,11 @@ table { border-collapse: collapse; }
h1 { font-size: 1.5rem; }
}
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }
++
++/* The home's showcase sections (openvibe-shared/showcase.css) inside the page column, which has its own gutter. */
++.wk-main .sc-hero, .wk-main .sc-sec, main .sc-hero, main .sc-sec { padding-left: 0; padding-right: 0; }
++main .sc-hero { padding-top: 16px; }
++main .sc-hero h1 { font-size: clamp(30px, 4.6vw, 46px); }
++main .sc-sec { margin-top: 36px; }
++main .sc-ic .ov-icon { --ovi-size: 28px !important; }
++#spaces { display: block; height: 8px; }
ddiff --git a/server/http/pages.js b/server/http/pages.js
iindex 2ca88ff..bd0afcc 100644
---- a/server/http/pages.js
++++ b/server/http/pages.js
@@@ -33,6 +33,7 @@ const ssr = require('openvibe-publishing/ssr');
const { renderPage } = require('../render/layout');
const views = require('../render/views');
const frame = require('openvibe-shared/frame');
++const showcase = require('openvibe-shared/showcase');
const content = require('../wiki/content');
const { actorMiddleware, resolveCitations, resolveBundleCitations, citationsFromForm } = require('./common');
const importer = require('../wiki/import');
@@@ -122,7 +123,7 @@ function createPages({ svc, viewers, platform, config, log = console, limits })
if (req.actor.subject) await svc.access.prepareVip(req.actor, (await svc.vipSpaces()).map((space) => ({ space }))); // VIP spaces the viewer may see
const [spaces, recent] = await Promise.all([svc.listSpaces(req.actor), svc.recentChanges(10)]);
send(req, res, 200, views.home({ spaces, recent, actor: req.actor }) + frame.shipped({ service: 'wiki', title: 'Recently shipped on OpenVibe.Wiki' }), {
-- robots: 'index, follow', cache: 'public', active: 'home', path: '/',
++ robots: 'index, follow', cache: 'public', active: 'home', path: '/', styles: [showcase.STYLESHEET],
jsonLd: seo.structuredData.webPage({ url: `${config.baseUrl}/`, name: 'OpenVibe.Wiki', description: 'Wiki spaces of the OpenVibe network.' }),
});
}));
ddiff --git a/server/render/layout.js b/server/render/layout.js
iindex 153186d..f75d9df 100644
---- a/server/render/layout.js
++++ b/server/render/layout.js
@@@ -84,6 +84,7 @@ ${head}
${appIcon.headTags({ site: 'network' })}
${feeds.map((f) => `<link rel="alternate" type="${f.type}" title="${esc(f.title)}" href="${f.href}">`).join('\n')}
<link rel="stylesheet" href="${asset('css/wiki.css')}">
++${(o.styles || []).map((name) => `<link rel="stylesheet" href="${esc(ovServe.url(name))}">`).join('\n')}
<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>
ddiff --git a/server/render/views.js b/server/render/views.js
iindex f99435f..a0ecdf9 100644
---- a/server/render/views.js
++++ b/server/render/views.js
@@@ -4,6 +4,7 @@
* unless raw()). Forms are plain HTML posts; nothing here needs JavaScript.
*/
const ssr = require('openvibe-publishing/ssr');
++const showcase = require('openvibe-shared/showcase');
const { figureHtml } = require('openvibe-publishing/media');
const { infoboxToText } = require('../wiki/content');
@@@ -35,9 +36,25 @@ function home({ spaces, recent, actor }) {
const official = spaces.filter((s) => s.kind === 'official');
const user = spaces.filter((s) => s.kind === 'user');
const list = (items) => items.length ? html`<ul class="wk-spaces">${items.map((s) => html`<li><a href="/s/${e(s.slug)}"><strong>${s.name}</strong></a>${s.visibility !== 'public' ? html` <span class="wk-tag">${s.visibility}</span>` : ''}${s.description ? html`<br><span class="wk-muted">${s.description}</span>` : ''}</li>`)}</ul>` : html`<p class="wk-muted">None yet.</p>`;
-- return html`<section class="wk-intro"><h1>OpenVibe.Wiki</h1>
--<p>Wiki spaces with page trees, revision history, citations and discussion. Official spaces are edited by OpenVibe staff; anyone signed in with an OpenVibe account can start a space of their own.</p>
--${actor && actor.subject ? html`<p><a class="wk-button" href="/new-space">Start a space</a></p>` : html`<p><a href="/auth/login?next=%2Fnew-space">Sign in</a> to start a space.</p>`}</section>
++ const start = actor && actor.subject ? { label: 'Start a space', href: '/new-space', primary: true } : { label: 'Sign in to start a space', href: '/auth/login?next=%2Fnew-space', primary: true };
++ // What OpenVibe.Wiki is for (openvibe-shared/showcase), then the spaces and what was published.
++ return html`${raw(showcase.hero({
++ eyebrow: 'OpenVibe.Wiki',
++ title: 'Knowledge,', accent: 'with sources',
++ lede: 'Wiki spaces with page trees, revision history, citations and discussion. Official spaces are edited by OpenVibe staff; anyone signed in with an OpenVibe account can start a space of their own.',
++ actions: [start, { label: 'Browse the spaces', href: '#spaces' }],
++ }) + showcase.features({
++ title: 'What a space gets',
++ items: [
++ { icon: 'ov:wiki', title: 'Page trees', text: 'Pages nest under pages, so a space reads like a book.' },
++ { icon: 'ov:history', title: 'Revision history', text: 'Every published revision is kept; compare or restore any of them.' },
++ { icon: 'ov:check', title: 'Citations', text: 'Claims carry their sources, listed with every page.' },
++ { icon: 'ov:community', title: 'Discussion', text: 'Each page has a thread on OpenVibe.Community.' },
++ { icon: 'ov:account', title: 'Roles and visibility', text: 'Public, members-only, VIP or private spaces, with editors you choose.' },
++ { icon: 'ov:search', title: 'Search and feeds', text: 'Full-text search across the spaces you can see, and Atom and JSON feeds.' },
++ ],
++ }))}
++<div id="spaces"></div>
<section><h2>Official spaces</h2>${list(official)}</section>
<section><h2>Community spaces</h2>${list(user)}</section>
<section><h2>Recently published</h2>${recent.length ? html`<ul class="wk-recent">${recent.map((r) => html`<li><a href="${wpath(r.space, r.page)}">${r.page.title}</a> <span class="wk-muted">in ${r.space.name} · ${t(r.page.revision_published_at)}</span></li>`)}</ul>` : html`<p class="wk-muted">Nothing published yet.</p>`}
ddiff --git a/test/perf-budget.test.js b/test/perf-budget.test.js
iindex 161acf4..cbaf18d 100644
---- a/test/perf-budget.test.js
++++ b/test/perf-budget.test.js
@@@ -12,14 +12,14 @@ const { spawn } = require('child_process');
const { measure, check, format } = require('openvibe-shared/perf-budget');
const BUDGETS = {
-- htmlRawKB: 22, // measured 17.3 (fresh database)
-- htmlBrotliKB: 5.5, // 4.4
++ htmlRawKB: 27.5, // measured 24.9 (fresh database; 2026-09-29 the showcase hero and features with six inline ring icons)
++ htmlBrotliKB: 7, // 6.3
jsFiles: 4, // 3
jsRawKB: 230, // 197.7
jsBrotliKB: 53, // 45.6
cssFiles: 2, // 1
-- cssRawKB: 7, // 5.5
-- cssBrotliKB: 2, // 1.5
++ cssRawKB: 18, // 16.3 (wiki.css + the cached /shared/showcase.css)
++ cssBrotliKB: 4.5, // 4.1
externalFiles: 1, // 0
};