openvibers/openvibe.shared rooms.js

rooms.js

main 5.5 KB · 63 lines · javascript

1/**
2 * openvibe-shared/rooms — OpenVibe's rooms (plan 2026-10-28 §3.1, §3.5): one table every site reads for a room's
3 * neighbourhood, its accent, its hero line and its motif, so a room looks like itself on every page that shows it.
4 *
5 * The accents sit every 25° of OKLCH hue. Each `dark` value passes AA against #0B0D12 (text, icons and fills on dark
6 * themes, with dark text on the fill); each `light` value passes AA against white (text and filled buttons on light
7 * themes, with white text). Put rooms.style(id) on the room's wrapper with the class ov-room: room.css then gives
8 * --room-accent (the right one for the theme's mode), --room-strong (text on the page) and --room-on (text on a fill).
9 *
10 * const rooms = require('openvibe-shared/rooms');
11 * rooms.get('surf') → { id, name, host, hood, hue, dark, light, line, motif, icon }
12 * rooms.style('surf') → '--room-dark:#00BEF6;--room-light:#0072AB'
13 * rooms.HOODS → { streams: 'Streams & places', … } (the menu's neighbourhoods; Network's frame is the authority)
14 * In the browser: window.OpenVibeRooms, the same.
15 */
16(function (root, factory) {
17 const api = factory();
18 if (typeof module === 'object' && module.exports) { module.exports = api; return; }
19 root.OpenVibeRooms = api;
20})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
21 'use strict';
22
23 const HOODS = Object.freeze({
24 watch: 'Watch & stream', talk: 'Talk & belong', play: 'Play', read: 'Read & ask',
25 shop: 'Shop & money', tools: 'Free tools', make: 'Make with AI', build: 'For developers',
26 });
27
28 // id, name in menus, host, neighbourhood, OKLCH hue, dark accent, light accent, hero line (≤ 8 words), kit icon, motif
29 const ROWS = [
30 ['fun', 'Fun', 'openvibe.fun', 'play', 350, '#F47DB9', '#A42C71', 'Something to do, alone, together, or live', 'spark', 'a city map where idea pins pop up and a quest card flips'],
31 ['shoes', 'Shoes', 'open.shoes', 'shop', 25, '#FF7E76', '#B02A2D', 'Every shoe, every market, the right price', 'shoe', 'a shoe drawn as one line, price tags from several stores sliding into one all-in price'],
32 ['tours', 'Tours', 'openvibe.tours', 'watch', 50, '#F98942', '#AA3900', 'Go anywhere: fly, stay, walk, watch', 'map', 'a plane\'s dotted arc landing on a map, then the walking route drawing itself'],
33 ['today', 'Today', 'openvibe.today', 'read', 75, '#E49900', '#994E00', 'Everything happening for you, today', 'calendar', 'the day\'s ring with events as dots and "now" sweeping; the brief\'s lines typing in'],
34 ['meme', 'Meme', 'openvibe.meme', 'play', 100, '#C3AC00', '#7B6100', 'The internet\'s meme database, rebuilt with AI', 'image', 'a family tree of memes growing branch by branch, stickers fanning out'],
35 ['domains', 'Domains', 'openvibe.domains', 'tools', 125, '#94BB3B', '#4D7100', 'Name it, price it, run it', 'globe', 'a name typing itself while extensions cycle, prices settling into a sorted list'],
36 ['casino', 'Casino', 'openvibe.casino', 'play', 150, '#51C672', '#007C25', 'Learn it, play it, never pay it', 'game', 'a card fan and chips, with a probability curve drawing beneath'],
37 ['exchange', 'Exchange', 'openvibe.exchange', 'build', 175, '#00CAA5', '#007F5E', 'Trade what people make', 'swap', 'two arrows looping an item between makers, and a passport card stamping "safe"'],
38 ['cam', 'Cam', 'openvibe.cam', 'watch', 200, '#00C7D2', '#007C89', 'Your camera, the world\'s cams, face to face', 'video', 'a shutter iris opening onto a grid of live cams, a flash, the photo flying to a gallery'],
39 ['surf', 'Surf', 'openvibe.surf', 'play', 225, '#00BEF6', '#0072AB', 'Ride maps, surf the web, surf what\'s on', 'wave', 'a first-person surf run: ramps, speed lines, the timer ticking'],
40 ['report', 'Report', 'openvibe.report', 'read', 250, '#50B0FF', '#0064BE', 'Every number on OpenVibe, honest', 'chart', 'live counters ticking, a line chart drawing itself, the after-show card sliding in'],
41 ['website', 'Website', 'openvibe.website', 'make', 275, '#8EA0FF', '#4B53C2', 'Serious sites, no login needed', 'computer', 'a browser frame assembling a real site from blocks while a cursor types the prompt'],
42 ['vision', 'Vision', 'openvibe.vision', 'read', 300, '#BB91FF', '#7444B4', 'See with the best model for the job', 'eye', 'an aperture with two models\' boxes racing on the same image, cost and time ticking'],
43 ['design', 'Design', 'openvibe.design', 'tools', 325, '#DD84E2', '#913797', 'Make it yours, find the best AI designer', 'palette', 'the theme orb: drag it and the whole page recolours live; an A/B vote flips'],
44 ];
45 const ROOMS = Object.freeze(Object.fromEntries(ROWS.map(([id, name, host, hood, hue, dark, light, line, icon, motif]) =>
46 [id, Object.freeze({ id, name, host, hood, hue, dark, light, line, icon, motif })])));
47 const IDS = Object.freeze(ROWS.map((r) => r[0]));
48
49 const byHost = new Map(ROWS.map((r) => [r[2], r[0]]));
50 /** A room by id or host ('surf', 'openvibe.surf', 'www.open.shoes'); null when it is not a room. */
51 function get(key) {
52 const k = String(key || '').toLowerCase().replace(/^www\./, '');
53 return ROOMS[k] || ROOMS[byHost.get(k)] || null;
54 }
55 /** The custom properties a room's wrapper carries (class ov-room); '' for an unknown room (the theme's accent stays). */
56 function style(key) {
57 const r = get(key);
58 return r ? `--room-dark:${r.dark};--room-light:${r.light}` : '';
59 }
60
61 return { HOODS, ROOMS, IDS, get, style, VERSION: 1 };
62});
63