openvibers/openvibe.shared AGENTS.md
AGENTS.md
| 1 | # AGENTS.md — OpenVibe.Shared |
| 2 | |
| 3 | ## Project overview |
| 4 | |
| 5 | `openvibe-shared` is the versioned UI and server-helpers package every OpenVibe site renders: the |
| 6 | OpenVibe Frame (navbar, the menu with its Chat and Vibe places, footer, panels), themes and design tokens, glyphs and app icons, SEO, |
| 7 | legal pages, analytics, readiness/metrics, egress and the web runtime. It is a library (MIT), not a |
| 8 | service: it owns no database, port or process, and nothing is deployed from this repository. |
| 9 | |
| 10 | - **Package root is the repository root.** `package.json` is at the root, so GitHub's tarball of a |
| 11 | tag installs directly. Entry: `index.js` (CommonJS exports for server code). |
| 12 | - **Browser files** are plain scripts served by a consumer at `/shared/<file>`; `files.js` is the |
| 13 | complete list of what may be served and must include every new browser file in the same release. |
| 14 | `serve.js` (`openvibe-shared/serve`) serves them with content-hashed URLs (`?v=`), ETags and |
| 15 | serve-time minification, plus `social/`, `icons/` and `manifest/<service>.webmanifest`. |
| 16 | - **Server modules** are required by name: `openvibe-shared/shell`, `seo`, `legal`, `ready`, |
| 17 | `metrics`, `config`, `csp`, `analytics`, `assets`, `agent-layer`, `test-runner`, `egress`, |
| 18 | `trace`, `indexnow`, `release`. |
| 19 | - **Design docs:** `docs/` (`docs/kit.md`, `docs/agent-layer.md`, `docs/agent-session.md`, |
| 20 | `docs/tokens.md`, `docs/forms.md`, `docs/player-startup.md`, `docs/home-pages.md`, |
| 21 | `docs/migration-plan.md`); architecture decisions in `docs/adr/`. |
| 22 | - **Build helpers:** `scripts/build-styles.js` (CSS bundles), `scripts/build-theme-loader.js` |
| 23 | (generated theme block), `scripts/build-icons.js`, `scripts/build-glyphs.js` (`ov-glyphs.js` and the sprite), |
| 24 | `scripts/build-navbar-icons.js` (the bar's set and the ring icons' solids, from `glyphs.js`), |
| 25 | `scripts/fa-to-ov.js` (a repository's Font Awesome markup into `data-ov-icon`), `scripts/create-site.js` (a new |
| 26 | site scaffold), `scripts/size-report.js`. |
| 27 | |
| 28 | ## Who calls it, what it calls |
| 29 | |
| 30 | Every site pins a release tag |
| 31 | (`"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/vX.Y.Z"`) |
| 32 | and mounts `require('openvibe-shared/serve').handler()` at `/shared`. Network also serves |
| 33 | `https://openvibe.network/shared/*` from the tag it pins. The package has one runtime dependency |
| 34 | (`jsonwebtoken`, for `auth-client`); `openvibe-contracts` is a devDependency the release tests |
| 35 | validate against. |
| 36 | |
| 37 | In the browser the shared files call OpenVibe.Network (session, theme and notification APIs, |
| 38 | realtime tickets, the changelog) and OpenVibe.Events (the notification bell's realtime stream). |
| 39 | On the server the helpers are configured by each consumer and call whatever that consumer passes |
| 40 | in — Shared owns no capability, grant or table. |
| 41 | |
| 42 | ## Commands |
| 43 | |
| 44 | ```bash |
| 45 | npm ci |
| 46 | npm test # every test/*.test.js, Node 22.22.1 in CI |
| 47 | npm test -- navbar icons # only files whose name contains a word |
| 48 | npm test -- --strict # a skipped file fails the run |
| 49 | npm run size # raw + brotli (q11) size of every browser file |
| 50 | node scripts/build-theme-loader.js |
| 51 | node scripts/build-styles.js |
| 52 | node scripts/build-navbar-icons.js # the bar's icons and the ring solids, from glyphs.js |
| 53 | node scripts/create-site.js my-site |
| 54 | ``` |
| 55 | |
| 56 | Tests are plain Node with stubbed browser globals; `*-chrome.test.js` starts headless Chrome and is |
| 57 | skipped (and shown as ○, never passed) when Chrome is absent. `test/run.js` uses |
| 58 | `test-runner.js` with 90 s per file, Chrome files serial, and one retry for a Chrome file. |
| 59 | |
| 60 | ## Architecture at a glance |
| 61 | |
| 62 | - **Frame:** `navbar.js`, `footer.js`, `frame.js`, `shell.js`, `appbar.js`, `bottom.js`, |
| 63 | `dock*.js`, `panels.js`, `island.js`. |
| 64 | - **Theme:** `theme-loader.js` (runs before first paint), `theme-sync.js`, `builtin-themes.js`, |
| 65 | `kit.js`/`kit.css`, `tokens.js`; Network owns theme authority. |
| 66 | - **Icons and marks:** `glyphs.js` (one registry: `NAMES`, `path`, `svg`, `fromFa`), `ov-glyphs.js`, |
| 67 | `nav-icons.js`, generated `ov-glyphs*.css`/fonts, `mark.js`/`ov-mark.js`, `app-icons.js`. |
| 68 | - **Release client:** `release-watch.js`, `release-update.js`, `release.json` handling |
| 69 | (`docs/adr`, ADR-016) — active-tab update coordination, mixed-version tests. |
| 70 | - **Web runtime:** `web-runtime.js` (`OVWebRuntime`, feature loading and route scopes), |
| 71 | `boost.js`, `soft.js`, `route-transition.js`, `cache-policy.js`, `openvibe-sw.js`/`sw.js`. |
| 72 | - **Server:** `seo.js` (head, sitemap, robots, llms.txt), `legal.js`, `csp.js`, `ready.js`, |
| 73 | `metrics.js`, `analytics/`, `egress.js`, `trace.js`, `config*.js`, `agent-layer.js`. |
| 74 | |
| 75 | ## Conventions |
| 76 | |
| 77 | - **CommonJS, 4-space indent, single quotes, semicolons.** No linter or formatter. |
| 78 | - **Browser files must not `require()` or name Node globals** (`test/browser-bundles.test.js`); |
| 79 | server-only code lives behind a subpath, never in a browser file. |
| 80 | - **Every public module file has an export**, and every export resolves; `config-core.js` and |
| 81 | `analytics/core.js` are deliberately private. |
| 82 | - **New browser file = add it to `files.js`** and, when it ships a public name, to the compatibility |
| 83 | policy in the README; `test/browser-files-complete.test.js` and the size report read the list. |
| 84 | - **Generated blocks are committed:** navbar and theme-loader generated blocks are regenerated by |
| 85 | their scripts and checked by tests. Never hand-edit a generated CSS/JS block. |
| 86 | - **Content-hashed assets only** (`assets.js`, `serve.url`); never add `?v=` by hand. |
| 87 | - **Glyph rules:** draw icons from the one registry (`glyphs.js`) with OpenVibe's own markup: |
| 88 | `<i data-ov-icon="eye">`, `<i data-ov-brand="github">` (`glyphs.markup()` on a server, `OVGlyphs.icon()` in a |
| 89 | page). Never add Font Awesome markup; `scripts/fa-to-ov.js` rewrites what is left, and a later release drops the |
| 90 | Font Awesome names entirely. No drawing comes from another icon set. |
| 91 | - **CSS is phone first:** the Frame and Kit styles start at the 390 px layout; test a phone width |
| 92 | before a desktop one. |
| 93 | - **Motion rule ("Calm reduces, only Off removes"):** reduced motion reduces animation; it does not |
| 94 | hide content or controls. |
| 95 | |
| 96 | ## Key pitfalls |
| 97 | |
| 98 | - **Releases are immutable.** Bump `package.json` + `CHANGELOG.md` (`Release vX.Y.Z`), commit, tag |
| 99 | `vX.Y.Z`, push main and the tag. Never move or delete a tag: consumer lockfiles pin its |
| 100 | integrity. Upgrade Network first, then the sites. |
| 101 | - **Size budgets are tests:** `navbar.js` 29 KB brotli, `release-watch.js` 5 KB, |
| 102 | `release-update.js` 3.5 KB, `web-runtime.js` 6.5 KB. Adding a script to the eager path is a |
| 103 | budget change, not a free edit. |
| 104 | - **The previous major stays servable** at `/shared/v<major>/<file>`; an unversioned path never |
| 105 | jumps a major silently (compatibility policy in the README). |
| 106 | - **CSP:** consumers build headers with `csp.js`; a browser file must not need `eval`, inline script |
| 107 | or a new origin without adding it to the policy and the CSP tests. |
| 108 | - **Analytics stores no personal data** and must honour opt-out (`test/analytics-privacy.test.js`); |
| 109 | request telemetry is aggregated by route template, never raw URL. |
| 110 | - **`egress.js` is the only outbound fetch for user-chosen URLs** (SSRF-safe, connect-time DNS); |
| 111 | `trace.js` forwards W3C trace headers only to loopback and OpenVibe hosts. |
| 112 | - **No build step for consumers:** everything under `/shared` is served from the installed package; |
| 113 | a new dependency must be browser-safe or it cannot go in `files.js`. |
| 114 | |
| 115 | ## Testing |
| 116 | |
| 117 | `npm test` runs every `test/*.test.js` in its own process; tests use `assert`, linkedom/stubbed |
| 118 | browser globals and local fixtures, never a live site. Release-guarding tests cover the size |
| 119 | budgets, the release manifest and mixed-version matrix, built-in icons, generated blocks, browser |
| 120 | files free of Node code, export resolution and analytics privacy. Chrome tests need a local Chrome; |
| 121 | `OV_SKIP_BROWSER=1` skips them. `npm run size` prints the raw and brotli sizes when a budget is close. |
| 122 |