openvibers/openvibe.network Commits

Launcher groups: people's products first, the building blocks under For developers (#318)

OP OpenVibers committed 20 days ago · 31b136bb59 · 3 files, +13 −8

* The launcher leads with what people use (Chat & community first, Agents & robots as a group) and puts the building blocks last under For developers

* The home's service map shows the new groups (For developers, Agents & robots)

Changes

ddiff --git a/server/frame/sites.js b/server/frame/sites.js
iindex a106df9e..899556a6 100644
---- a/server/frame/sites.js
++++ b/server/frame/sites.js
@@@ -31,13 +31,16 @@ const byHost = new Map(SITES.map(s => [s.host, s]));
// The launcher (openvibe-shared navbar) lists every open site under one of these groups, most used first within
// each. A site missing here lands in the last group, so a new manifest is never left out of the menu.
++// Plan track K (the owner, 2026-10-24: consumer-friendly products, the developer side on Services): what people use
++// first, agents and robots as their own group, and the building blocks last under "For developers".
const GROUPS = [
++ { id: 'talk', name: 'Chat & community', sites: ['chat', 'community', 'wiki', 'news', 'blog'] },
{ id: 'watch', name: 'Watch & stream', sites: ['live', 'media-hub', 'pics', 'stream', 'tips', 'vip'] },
-- { id: 'create', name: 'Create & play', sites: ['games', 'play', 'space', 'blog'] },
-- { id: 'talk', name: 'Talk & learn', sites: ['chat', 'community', 'wiki', 'news'] },
-- { id: 'everyday', name: 'Shop & everyday', sites: ['deals', 'coupons', 'reviews', 'food', 'rent', 'homes', 'trade', 'work', 'host'] },
-- { id: 'build', name: 'Build & automate', sites: ['tools', 'codes', 'run', 'actor', 'ai', 'bot', 'services', 'events', 'watch', 'zone', 'media', 'download'] },
-- { id: 'you', name: 'Your OpenVibe', sites: ['network', 'search', 'help', 'quest', 'inventory'] },
++ { id: 'agents', name: 'Agents & robots', sites: ['actor', 'bot', 'codes', 'watch'] },
++ { id: 'everyday', name: 'Shop & everyday', sites: ['deals', 'coupons', 'reviews', 'food', 'rent', 'homes', 'work', 'trade', 'host'] },
++ { id: 'create', name: 'Create & play', sites: ['games', 'space', 'tools', 'download', 'quest'] },
++ { id: 'you', name: 'Your OpenVibe', sites: ['network', 'search', 'help', 'inventory'] },
++ { id: 'build', name: 'For developers', sites: ['services', 'ai', 'run', 'zone', 'events', 'media', 'play'] },
];
const groupOf = (id) => (GROUPS.find(g => g.sites.includes(id)) || GROUPS[GROUPS.length - 1]).id;
ddiff --git a/test/frame.test.js b/test/frame.test.js
iindex 509d9c83..4f65bf23 100644
---- a/test/frame.test.js
++++ b/test/frame.test.js
@@@ -17,12 +17,14 @@ let p = svc.payloadFor('openvibe.media');
assert.deepEqual(p.nav.filter(n => !n.of).map(n => n.id), ['live', 'tools', 'space', 'community', 'games', 'media', 'network', 'chat', 'services', 'blog', 'wiki', 'news', 'reviews', 'tips', 'vip', 'trade', 'host', 'deals', 'coupons', 'stream', 'media-hub', 'bot', 'codes', 'actor', 'food', 'help', 'work', 'quest', 'rent', 'watch', 'inventory', 'events', 'ai', 'search', 'run', 'play', 'zone'], 'cold start follows the base order');
// The launcher: every open site in one of the groups, and the products other services serve on their own domains
// right after their site (Pics and Download after Video, Homes after Rent).
--assert.deepStrictEqual(p.groups.map(g => g.id), ['watch', 'create', 'talk', 'everyday', 'build', 'you']);
++assert.deepStrictEqual(p.groups.map(g => g.id), ['talk', 'watch', 'agents', 'everyday', 'create', 'you', 'build'], 'what people use first, the building blocks last (plan track K)');
++assert.strictEqual(p.groups.find(g => g.id === 'build').name, 'For developers');
assert.ok(p.nav.every(n => p.groups.some(g => g.id === n.group)), 'every entry has a group');
assert.deepStrictEqual(p.nav.filter(n => n.of).map(n => [n.id, n.of, n.url]), [['pics', 'media-hub', 'https://openvibe.pics/'], ['download', 'media-hub', 'https://openvibe.download/'], ['homes', 'rent', 'https://openvibe.homes/']]);
const at = (id) => p.nav.findIndex(n => n.id === id);
assert.ok(at('pics') === at('media-hub') + 1 && at('homes') === at('rent') + 1, 'a product follows its site');
--assert.deepStrictEqual([p.nav[at('media-hub')].icon, p.nav[at('media-hub')].group, p.nav[at('homes')].group, p.nav[at('tools')].group], ['video', 'watch', 'everyday', 'build'], 'Video draws the video icon (there is no media-hub icon)');
++assert.deepStrictEqual([p.nav[at('media-hub')].icon, p.nav[at('media-hub')].group, p.nav[at('homes')].group, p.nav[at('tools')].group], ['video', 'watch', 'everyday', 'create'], 'Video draws the video icon (there is no media-hub icon)');
++assert.deepStrictEqual(['actor', 'bot', 'run', 'zone'].map((id) => p.nav[at(id)].group), ['agents', 'agents', 'build', 'build'], 'agents and robots for people, compute and storage for developers');
assert.strictEqual(p.nav.length, 40);
assert.strictEqual(p.nav.find(n => n.id === 'space').url, 'https://openvibe.space/', 'Space keeps its own home (the forum returned to Community, 0.118.0)');
assert.strictEqual(p.nav.find(n => n.id === 'community').url, 'https://openvibe.community/', 'Community: the forum, pastes and Pulse');
ddiff --git a/test/home-front-door.test.js b/test/home-front-door.test.js
iindex 12deed95..7aa2b7eb 100644
---- a/test/home-front-door.test.js
++++ b/test/home-front-door.test.js
@@@ -107,7 +107,7 @@ assert.ok(faqLd.mainEntity.length >= 5, 'the FAQ has its questions');
faqLd.mainEntity.forEach((q) => assert.ok(html.includes(`<h3>${q.name.replace(/'/g, '&#39;')}</h3>`), `the FAQ shows "${q.name}"`));
assert.ok(faqLd.mainEntity.some((q) => /separate account/.test(q.name)), "Contracts' network FAQ is included");
// The service map groups the sites the way the launcher does; numbers say only what was read.
--assert.ok(/<h3 class="home-group">Watch &amp; stream<\/h3>/.test(html) && /<h3 class="home-group">Build &amp; automate<\/h3>/.test(html), 'the sites are grouped');
++assert.ok(/<h3 class="home-group">Watch &amp; stream<\/h3>/.test(html) && /<h3 class="home-group">For developers<\/h3>/.test(html) && /<h3 class="home-group">Agents &amp; robots<\/h3>/.test(html), 'the sites are grouped');
assert.ok(/<section class="net-num"/.test(html) && /sites, one account/.test(html), 'the numbers panel renders');
assert.ok(!/services up/.test(html) && !/accounts<\/span>/.test(html), 'numbers nobody read are left out');
assert.ok(!/Latest recordings|New jobs|Fresh coupon codes/.test(html), 'an empty column is left out');