openvibers/openvibe.sites Commits

OpenVibe.Sites: static front pages + nginx vhosts for the 13 domains without an app yet

OP OpenVibers committed 18 Sept 2026 · 5f6c46ce39 · 70 files, +3740 −0


Changes

ddiff --git a/.gitignore b/.gitignore
nnew file mode 100644
iindex 0000000..c2658d7
---- /dev/null
++++ b/.gitignore
@@@ -0,0 +1 @@
++node_modules/
ddiff --git a/README.md b/README.md
nnew file mode 100644
iindex 0000000..a2a90cc
---- /dev/null
++++ b/README.md
@@@ -0,0 +1,20 @@
++# OpenVibe.Sites
++
++Static front pages for the OpenVibe domains that are not full applications yet
++(`openvibe.chat`, `.codes`, `.blog`, `.wiki`, `.news`, `.reviews`, `.tips`, `.vip`, `.trade`,
++`.host`, `.deals`, `.coupons`, `openre.stream`). One catalog (`sites.json`), one template
++(`build.js`), real pages: what the site will be, what to use on the network meanwhile, the whole
++network, sign-in — with the shared navbar, footer and theme loader from openvibe.network, full
++SEO (canonical, Open Graph, Twitter, JSON-LD, robots, sitemap, manifest).
++
++```
++node build.js # dist/<domain>/… + deploy/nginx/<domain>.conf
++node build.js --check # fails when dist/ is stale
++```
++
++Deploy (host): the repo lives at `/opt/openvibe.sites`; `deploy/scripts/deploy.sh` rebuilds, installs
++the vhosts into `/etc/nginx/sites-available`, enables them and reloads nginx. Each domain has a
++Let's Encrypt wildcard certificate (`certbot --dns-cloudflare`, see the host's renewal configs).
++
++When a domain becomes a real app, delete it from `sites.json`, remove its vhost, and point the
++domain's nginx block at the new service — nothing else references it.
ddiff --git a/build.js b/build.js
nnew file mode 100644
iindex 0000000..36c0c36
---- /dev/null
++++ b/build.js
@@@ -0,0 +1,283 @@
++#!/usr/bin/env node
++'use strict';
++/**
++ * OpenVibe.Sites — static front pages for the network's domains that are not full apps yet.
++ *
++ * node build.js → dist/<domain>/{index.html,robots.txt,sitemap.xml,manifest.webmanifest}
++ * node build.js --check → exit 1 when dist/ is stale (CI / deploy guard)
++ *
++ * One template, one catalog (sites.json). Every page is real content for people and crawlers:
++ * what the site will be, what to use meanwhile, the whole network, sign-in — with the shared
++ * navbar/footer/theme loader from openvibe.network so the domain already feels like the rest of
++ * the network. No build step at request time: nginx serves the files.
++ */
++const fs = require('fs');
++const path = require('path');
++
++const ROOT = __dirname;
++const DIST = path.join(ROOT, 'dist');
++const catalog = JSON.parse(fs.readFileSync(path.join(ROOT, 'sites.json'), 'utf8'));
++const NET = catalog.network;
++const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
++const today = new Date().toISOString().slice(0, 10);
++
++function hexToRgb(hex) { const m = String(hex).replace('#', ''); const n = parseInt(m.length === 3 ? m.split('').map(c => c + c).join('') : m, 16); return `${(n >> 16) & 255},${(n >> 8) & 255},${n & 255}`; }
++
++function page(site) {
++ const core = site.core || NET.core;
++ const url = `https://${site.domain}/`;
++ const title = `${site.name} — ${site.tagline}`;
++ const ogImage = `${NET.networkUrl}/assets/logo-512.png`;
++ const others = NET.liveSites.filter(s => s.url !== url.slice(0, -1));
++ const siblings = catalog.sites.filter(s => s.domain !== site.domain);
++ const ld = {
++ '@context': 'https://schema.org',
++ '@graph': [
++ { '@type': 'WebSite', '@id': `${url}#site`, url, name: site.name, description: site.description, inLanguage: 'en',
++ publisher: { '@type': 'Organization', '@id': `${NET.networkUrl}/#org`, name: 'OpenVibe', url: `${NET.networkUrl}/`, logo: ogImage, sameAs: [NET.github, NET.discord] },
++ isPartOf: { '@type': 'WebSite', '@id': `${NET.networkUrl}/#site`, name: 'OpenVibe.Network', url: `${NET.networkUrl}/` } },
++ { '@type': 'WebPage', '@id': `${url}#page`, url, name: title, description: site.description, isPartOf: { '@id': `${url}#site` }, datePublished: today, dateModified: today,
++ breadcrumb: { '@type': 'BreadcrumbList', itemListElement: [{ '@type': 'ListItem', position: 1, name: 'OpenVibe', item: `${NET.networkUrl}/` }, { '@type': 'ListItem', position: 2, name: site.name, item: url }] } },
++ ],
++ };
++ return `<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>${esc(title)}</title>
++<meta name="description" content="${esc(site.description)}">
++<meta name="keywords" content="${esc(site.keywords || '')}">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="${esc(site.accent)}">
++<link rel="canonical" href="${url}">
++<link rel="icon" href="${NET.networkUrl}/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="${url}">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="${esc(site.name)}">
++<meta property="og:url" content="${url}">
++<meta property="og:title" content="${esc(title)}">
++<meta property="og:description" content="${esc(site.description)}">
++<meta property="og:image" content="${ogImage}">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="${esc(title)}">
++<meta name="twitter:description" content="${esc(site.description)}">
++<meta name="twitter:image" content="${ogImage}">
++<script type="application/ld+json">${JSON.stringify(ld)}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="${NET.networkUrl}/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:${esc(site.accent)};--site-rgb:${hexToRgb(site.accent)}}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid ${esc(site.icon)}" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="${esc(site.tld)}"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>${esc(core)}<span class="d">.</span><span class="tld">${esc(site.name.split('.').pop())}</span></h1>
++ <div class="tag">${esc(site.tagline)}</div>
++ <p class="lead">${esc(site.description)}</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="${NET.networkUrl}/login?return=${encodeURIComponent(url)}"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="${NET.networkUrl}/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="${esc(NET.discord)}" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What ${esc(site.name)} will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ ${site.pillars.map(([h, d]) => `<div class="card"><div class="ic"><i class="fa-solid ${esc(site.icon)}" aria-hidden="true"></i></div><b>${esc(h)}</b><span>${esc(d)}</span></div>`).join('\n ')}
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ ${(site.meanwhile || []).map(([h, href, d]) => `<a class="card" href="${esc(href)}"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>${esc(h)}</b><span>${esc(d)}</span><span class="go">${esc(href.replace(/^https?:\/\//, '').replace(/\/$/, ''))} →</span></a>`).join('\n ')}
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ ${others.map(s => `<a class="card" href="${esc(s.url)}"><div class="ic"><i class="fa-solid ${esc(s.icon)}" aria-hidden="true"></i></div><b>${esc(s.name)}</b><span>${esc(s.desc)}</span><span class="go">${esc(s.url.replace(/^https?:\/\//, ''))} →</span></a>`).join('\n ')}
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ ${siblings.map(s => `<a href="https://${esc(s.domain)}/"><i class="fa-solid ${esc(s.icon)}" aria-hidden="true"></i>${esc(s.name)}</a>`).join('\n ')}
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="${esc(site.tld)}"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="${esc(NET.github)}" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="${NET.networkUrl}/shared/ov-mark.js" async></script>
++<script src="${NET.networkUrl}/shared/navbar.js"></script>
++<script src="${NET.networkUrl}/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: '${esc(site.tld)}', apiBase: '${NET.networkUrl}', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: '${NET.networkUrl}/#network', external: false }], history: { type: 'page', title: '${esc(site.name)}' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: '${esc(site.tld)}', variant: 'full', links: [{ heading: '${esc(site.name)}', items: [{ name: 'Sign in', url: '${NET.networkUrl}/login?return=${encodeURIComponent(url)}' }, { name: 'The network', url: '${NET.networkUrl}/#network' }, { name: 'Discord', url: '${esc(NET.discord)}' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
++`;
++}
++
++function robots(site) { return `User-agent: *\nAllow: /\nDisallow: /auth/\nSitemap: https://${site.domain}/sitemap.xml\n`; }
++function sitemap(site) { return `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n <url><loc>https://${site.domain}/</loc><lastmod>${today}</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>\n</urlset>\n`; }
++function manifest(site) { return JSON.stringify({ name: site.name, short_name: site.name.split('.').pop(), start_url: '/', display: 'standalone', background_color: '#0a0f1c', theme_color: site.accent, icons: [{ src: `${NET.networkUrl}/assets/logo-192.png`, sizes: '192x192', type: 'image/png' }, { src: `${NET.networkUrl}/assets/logo-512.png`, sizes: '512x512', type: 'image/png' }] }, null, 2) + '\n'; }
++
++/** nginx vhost: static root, wildcard cert, www → apex, long cache for the immutable bits. */
++function vhost(site) {
++ const d = site.domain;
++ return `# ${d} — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name ${d} www.${d};
++ return 301 https://${d}$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.${d};
++ ssl_certificate /etc/letsencrypt/live/${d}/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/${d}/privkey.pem;
++ return 301 https://${d}$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name ${d};
++
++ ssl_certificate /etc/letsencrypt/live/${d}/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/${d}/privkey.pem;
++
++ root /opt/openvibe.sites/dist/${d};
++ index index.html;
++
++ access_log /var/log/nginx/${d}.access.log;
++ error_log /var/log/nginx/${d}.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /\.(?!well-known) { deny all; }
++}
++`;
++}
++
++function build() {
++ const out = {};
++ for (const site of catalog.sites) {
++ out[`${site.domain}/index.html`] = page(site);
++ out[`${site.domain}/robots.txt`] = robots(site);
++ out[`${site.domain}/sitemap.xml`] = sitemap(site);
++ out[`${site.domain}/manifest.webmanifest`] = manifest(site);
++ out[`../deploy/nginx/${site.domain}.conf`] = vhost(site);
++ }
++ return out;
++}
++
++const files = build();
++if (process.argv.includes('--check')) {
++ let stale = 0;
++ for (const [rel, content] of Object.entries(files)) {
++ const p = path.join(DIST, rel);
++ // lastmod/datePublished change daily; compare with dates neutralised.
++ const norm = (s) => String(s).replace(/\d{4}-\d{2}-\d{2}/g, 'DATE');
++ if (!fs.existsSync(p) || norm(fs.readFileSync(p, 'utf8')) !== norm(content)) { console.error(`stale: ${rel}`); stale++; }
++ }
++ process.exit(stale ? 1 : 0);
++}
++for (const [rel, content] of Object.entries(files)) {
++ const p = path.join(DIST, rel);
++ fs.mkdirSync(path.dirname(p), { recursive: true });
++ fs.writeFileSync(p, content);
++}
++console.log(`built ${catalog.sites.length} sites → dist/`);
ddiff --git a/deploy/nginx/openre.stream.conf b/deploy/nginx/openre.stream.conf
nnew file mode 100644
iindex 0000000..350b62b
---- /dev/null
++++ b/deploy/nginx/openre.stream.conf
@@@ -0,0 +1,52 @@
++# openre.stream — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openre.stream www.openre.stream;
++ return 301 https://openre.stream$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openre.stream;
++ ssl_certificate /etc/letsencrypt/live/openre.stream/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openre.stream/privkey.pem;
++ return 301 https://openre.stream$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openre.stream;
++
++ ssl_certificate /etc/letsencrypt/live/openre.stream/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openre.stream/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openre.stream;
++ index index.html;
++
++ access_log /var/log/nginx/openre.stream.access.log;
++ error_log /var/log/nginx/openre.stream.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.blog.conf b/deploy/nginx/openvibe.blog.conf
nnew file mode 100644
iindex 0000000..40a1799
---- /dev/null
++++ b/deploy/nginx/openvibe.blog.conf
@@@ -0,0 +1,52 @@
++# openvibe.blog — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.blog www.openvibe.blog;
++ return 301 https://openvibe.blog$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.blog;
++ ssl_certificate /etc/letsencrypt/live/openvibe.blog/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.blog/privkey.pem;
++ return 301 https://openvibe.blog$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.blog;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.blog/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.blog/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.blog;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.blog.access.log;
++ error_log /var/log/nginx/openvibe.blog.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.chat.conf b/deploy/nginx/openvibe.chat.conf
nnew file mode 100644
iindex 0000000..809f1bb
---- /dev/null
++++ b/deploy/nginx/openvibe.chat.conf
@@@ -0,0 +1,52 @@
++# openvibe.chat — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.chat www.openvibe.chat;
++ return 301 https://openvibe.chat$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.chat;
++ ssl_certificate /etc/letsencrypt/live/openvibe.chat/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.chat/privkey.pem;
++ return 301 https://openvibe.chat$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.chat;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.chat/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.chat/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.chat;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.chat.access.log;
++ error_log /var/log/nginx/openvibe.chat.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.codes.conf b/deploy/nginx/openvibe.codes.conf
nnew file mode 100644
iindex 0000000..d955675
---- /dev/null
++++ b/deploy/nginx/openvibe.codes.conf
@@@ -0,0 +1,52 @@
++# openvibe.codes — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.codes www.openvibe.codes;
++ return 301 https://openvibe.codes$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.codes;
++ ssl_certificate /etc/letsencrypt/live/openvibe.codes/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.codes/privkey.pem;
++ return 301 https://openvibe.codes$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.codes;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.codes/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.codes/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.codes;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.codes.access.log;
++ error_log /var/log/nginx/openvibe.codes.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.coupons.conf b/deploy/nginx/openvibe.coupons.conf
nnew file mode 100644
iindex 0000000..abc57e7
---- /dev/null
++++ b/deploy/nginx/openvibe.coupons.conf
@@@ -0,0 +1,52 @@
++# openvibe.coupons — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.coupons www.openvibe.coupons;
++ return 301 https://openvibe.coupons$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.coupons;
++ ssl_certificate /etc/letsencrypt/live/openvibe.coupons/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.coupons/privkey.pem;
++ return 301 https://openvibe.coupons$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.coupons;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.coupons/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.coupons/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.coupons;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.coupons.access.log;
++ error_log /var/log/nginx/openvibe.coupons.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.deals.conf b/deploy/nginx/openvibe.deals.conf
nnew file mode 100644
iindex 0000000..db8d310
---- /dev/null
++++ b/deploy/nginx/openvibe.deals.conf
@@@ -0,0 +1,52 @@
++# openvibe.deals — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.deals www.openvibe.deals;
++ return 301 https://openvibe.deals$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.deals;
++ ssl_certificate /etc/letsencrypt/live/openvibe.deals/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.deals/privkey.pem;
++ return 301 https://openvibe.deals$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.deals;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.deals/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.deals/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.deals;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.deals.access.log;
++ error_log /var/log/nginx/openvibe.deals.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.host.conf b/deploy/nginx/openvibe.host.conf
nnew file mode 100644
iindex 0000000..f136d7d
---- /dev/null
++++ b/deploy/nginx/openvibe.host.conf
@@@ -0,0 +1,52 @@
++# openvibe.host — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.host www.openvibe.host;
++ return 301 https://openvibe.host$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.host;
++ ssl_certificate /etc/letsencrypt/live/openvibe.host/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.host/privkey.pem;
++ return 301 https://openvibe.host$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.host;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.host/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.host/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.host;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.host.access.log;
++ error_log /var/log/nginx/openvibe.host.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.news.conf b/deploy/nginx/openvibe.news.conf
nnew file mode 100644
iindex 0000000..699790e
---- /dev/null
++++ b/deploy/nginx/openvibe.news.conf
@@@ -0,0 +1,52 @@
++# openvibe.news — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.news www.openvibe.news;
++ return 301 https://openvibe.news$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.news;
++ ssl_certificate /etc/letsencrypt/live/openvibe.news/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.news/privkey.pem;
++ return 301 https://openvibe.news$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.news;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.news/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.news/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.news;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.news.access.log;
++ error_log /var/log/nginx/openvibe.news.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.reviews.conf b/deploy/nginx/openvibe.reviews.conf
nnew file mode 100644
iindex 0000000..2bd4125
---- /dev/null
++++ b/deploy/nginx/openvibe.reviews.conf
@@@ -0,0 +1,52 @@
++# openvibe.reviews — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.reviews www.openvibe.reviews;
++ return 301 https://openvibe.reviews$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.reviews;
++ ssl_certificate /etc/letsencrypt/live/openvibe.reviews/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.reviews/privkey.pem;
++ return 301 https://openvibe.reviews$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.reviews;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.reviews/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.reviews/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.reviews;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.reviews.access.log;
++ error_log /var/log/nginx/openvibe.reviews.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.tips.conf b/deploy/nginx/openvibe.tips.conf
nnew file mode 100644
iindex 0000000..29a2b34
---- /dev/null
++++ b/deploy/nginx/openvibe.tips.conf
@@@ -0,0 +1,52 @@
++# openvibe.tips — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.tips www.openvibe.tips;
++ return 301 https://openvibe.tips$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.tips;
++ ssl_certificate /etc/letsencrypt/live/openvibe.tips/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.tips/privkey.pem;
++ return 301 https://openvibe.tips$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.tips;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.tips/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.tips/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.tips;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.tips.access.log;
++ error_log /var/log/nginx/openvibe.tips.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.trade.conf b/deploy/nginx/openvibe.trade.conf
nnew file mode 100644
iindex 0000000..004f350
---- /dev/null
++++ b/deploy/nginx/openvibe.trade.conf
@@@ -0,0 +1,52 @@
++# openvibe.trade — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.trade www.openvibe.trade;
++ return 301 https://openvibe.trade$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.trade;
++ ssl_certificate /etc/letsencrypt/live/openvibe.trade/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.trade/privkey.pem;
++ return 301 https://openvibe.trade$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.trade;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.trade/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.trade/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.trade;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.trade.access.log;
++ error_log /var/log/nginx/openvibe.trade.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.vip.conf b/deploy/nginx/openvibe.vip.conf
nnew file mode 100644
iindex 0000000..a54446c
---- /dev/null
++++ b/deploy/nginx/openvibe.vip.conf
@@@ -0,0 +1,52 @@
++# openvibe.vip — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.vip www.openvibe.vip;
++ return 301 https://openvibe.vip$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.vip;
++ ssl_certificate /etc/letsencrypt/live/openvibe.vip/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.vip/privkey.pem;
++ return 301 https://openvibe.vip$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.vip;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.vip/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.vip/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.vip;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.vip.access.log;
++ error_log /var/log/nginx/openvibe.vip.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/nginx/openvibe.wiki.conf b/deploy/nginx/openvibe.wiki.conf
nnew file mode 100644
iindex 0000000..f8fb4af
---- /dev/null
++++ b/deploy/nginx/openvibe.wiki.conf
@@@ -0,0 +1,52 @@
++# openvibe.wiki — static front page (OpenVibe.Sites). Generated by build.js; edit sites.json, not this.
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.wiki www.openvibe.wiki;
++ return 301 https://openvibe.wiki$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.wiki;
++ ssl_certificate /etc/letsencrypt/live/openvibe.wiki/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.wiki/privkey.pem;
++ return 301 https://openvibe.wiki$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.wiki;
++
++ ssl_certificate /etc/letsencrypt/live/openvibe.wiki/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.wiki/privkey.pem;
++
++ root /opt/openvibe.sites/dist/openvibe.wiki;
++ index index.html;
++
++ access_log /var/log/nginx/openvibe.wiki.access.log;
++ error_log /var/log/nginx/openvibe.wiki.error.log;
++
++ add_header X-Content-Type-Options nosniff always;
++ add_header X-Frame-Options SAMEORIGIN always;
++ add_header Referrer-Policy strict-origin-when-cross-origin always;
++ add_header Strict-Transport-Security "max-age=31536000" always;
++
++ gzip on;
++ gzip_types text/html text/plain text/css application/json application/javascript application/xml image/svg+xml application/manifest+json;
++
++ location = /robots.txt { add_header Cache-Control "public, max-age=3600"; }
++ location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; types { application/xml xml; } }
++ location = /manifest.webmanifest { types { application/manifest+json webmanifest; } add_header Cache-Control "public, max-age=86400"; }
++
++ location / {
++ add_header Cache-Control "public, max-age=600";
++ try_files $uri $uri/ /index.html;
++ }
++
++ location ~ /.(?!well-known) { deny all; }
++}
ddiff --git a/deploy/scripts/deploy.sh b/deploy/scripts/deploy.sh
nnew file mode 100755
iindex 0000000..e266054
---- /dev/null
++++ b/deploy/scripts/deploy.sh
@@@ -0,0 +1,15 @@
++#!/bin/bash
++# OpenVibe.Sites — pull, rebuild, install vhosts, reload nginx. Run on the host:
++# sudo -u ubuntu git -C /opt/openvibe.sites pull --ff-only && /opt/openvibe.sites/deploy/scripts/deploy.sh
++set -euo pipefail
++REPO="${REPO:-/opt/openvibe.sites}"
++cd "$REPO"
++node build.js
++changed=0
++for conf in deploy/nginx/*.conf; do
++ name=$(basename "$conf")
++ if ! cmp -s "$conf" "/etc/nginx/sites-available/$name"; then sudo install -m 644 "$conf" "/etc/nginx/sites-available/$name"; changed=1; fi
++ [ -L "/etc/nginx/sites-enabled/$name" ] || { sudo ln -s "/etc/nginx/sites-available/$name" "/etc/nginx/sites-enabled/$name"; changed=1; }
++done
++if [ "$changed" = 1 ]; then sudo nginx -t && sudo systemctl reload nginx && echo "[sites] nginx reloaded"; else echo "[sites] vhosts unchanged"; fi
++echo "[sites] $(ls dist | wc -l) sites in place"
ddiff --git a/dist/openre.stream/index.html b/dist/openre.stream/index.html
nnew file mode 100644
iindex 0000000..cc6f998
---- /dev/null
++++ b/dist/openre.stream/index.html
@@@ -0,0 +1,167 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenRe.Stream — Ingest and restream, in the open.</title>
++<meta name="description" content="OpenRe.Stream is the ingest and restream infrastructure behind OpenVibe.Live: RTMP, WHIP and SRT ingest, stream lifecycle, restream destinations and output status — the plumbing, documented and open.">
++<meta name="keywords" content="openre stream, rtmp ingest, whip, srt, restream, open source streaming infrastructure">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#ef4444">
++<link rel="canonical" href="https://openre.stream/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openre.stream/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenRe.Stream">
++<meta property="og:url" content="https://openre.stream/">
++<meta property="og:title" content="OpenRe.Stream — Ingest and restream, in the open.">
++<meta property="og:description" content="OpenRe.Stream is the ingest and restream infrastructure behind OpenVibe.Live: RTMP, WHIP and SRT ingest, stream lifecycle, restream destinations and output status — the plumbing, documented and open.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenRe.Stream — Ingest and restream, in the open.">
++<meta name="twitter:description" content="OpenRe.Stream is the ingest and restream infrastructure behind OpenVibe.Live: RTMP, WHIP and SRT ingest, stream lifecycle, restream destinations and output status — the plumbing, documented and open.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openre.stream/#site","url":"https://openre.stream/","name":"OpenRe.Stream","description":"OpenRe.Stream is the ingest and restream infrastructure behind OpenVibe.Live: RTMP, WHIP and SRT ingest, stream lifecycle, restream destinations and output status — the plumbing, documented and open.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openre.stream/#page","url":"https://openre.stream/","name":"OpenRe.Stream — Ingest and restream, in the open.","description":"OpenRe.Stream is the ingest and restream infrastructure behind OpenVibe.Live: RTMP, WHIP and SRT ingest, stream lifecycle, restream destinations and output status — the plumbing, documented and open.","isPartOf":{"@id":"https://openre.stream/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenRe.Stream","item":"https://openre.stream/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#ef4444;--site-rgb:239,68,68}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="stream"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenRe<span class="d">.</span><span class="tld">Stream</span></h1>
++ <div class="tag">Ingest and restream, in the open.</div>
++ <p class="lead">OpenRe.Stream is the ingest and restream infrastructure behind OpenVibe.Live: RTMP, WHIP and SRT ingest, stream lifecycle, restream destinations and output status — the plumbing, documented and open.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenre.stream%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenRe.Stream will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i></div><b>Ingest</b><span>RTMP, WHIP/WebRTC and SRT, with keys and lifecycle in one place.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i></div><b>Restream</b><span>Twitch, YouTube, Kick, SRT and RobotStreamer destinations.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i></div><b>Status</b><span>Live acknowledgement, errors relayed in plain words, uptime.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i></div><b>Open</b><span>Run it yourself; the code is on GitHub.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live/broadcast"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Go live on OpenVibe.Live</b><span>Ingest and restreaming run inside Live today.</span><span class="go">openvibe.live/broadcast →</span></a>
++ <a class="card" href="https://github.com/OpenVibers/OpenVibe.Live/blob/main/docs/restreaming.md"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Restreaming docs</b><span>How the restream paths work.</span><span class="go">github.com/OpenVibers/OpenVibe.Live/blob/main/docs/restreaming.md →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="stream"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'stream', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenRe.Stream' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'stream', variant: 'full', links: [{ heading: 'OpenRe.Stream', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenre.stream%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openre.stream/manifest.webmanifest b/dist/openre.stream/manifest.webmanifest
nnew file mode 100644
iindex 0000000..7e0a11f
---- /dev/null
++++ b/dist/openre.stream/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenRe.Stream",
++ "short_name": "Stream",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#ef4444",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openre.stream/robots.txt b/dist/openre.stream/robots.txt
nnew file mode 100644
iindex 0000000..3e7edbe
---- /dev/null
++++ b/dist/openre.stream/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openre.stream/sitemap.xml
ddiff --git a/dist/openre.stream/sitemap.xml b/dist/openre.stream/sitemap.xml
nnew file mode 100644
iindex 0000000..58a9565
---- /dev/null
++++ b/dist/openre.stream/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openre.stream/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.blog/index.html b/dist/openvibe.blog/index.html
nnew file mode 100644
iindex 0000000..5bce31d
---- /dev/null
++++ b/dist/openvibe.blog/index.html
@@@ -0,0 +1,167 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Blog — Long-form, yours to keep.</title>
++<meta name="description" content="OpenVibe.Blog is the publishing home of the OpenVibe network: the official OpenVibe blog and blogs for every member — drafts, scheduled posts, media-rich writing, comments and feeds, with your OpenVibe account.">
++<meta name="keywords" content="openvibe blog, community blog, open source blogging">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#f472b6">
++<link rel="canonical" href="https://openvibe.blog/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.blog/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Blog">
++<meta property="og:url" content="https://openvibe.blog/">
++<meta property="og:title" content="OpenVibe.Blog — Long-form, yours to keep.">
++<meta property="og:description" content="OpenVibe.Blog is the publishing home of the OpenVibe network: the official OpenVibe blog and blogs for every member — drafts, scheduled posts, media-rich writing, comments and feeds, with your OpenVibe account.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Blog — Long-form, yours to keep.">
++<meta name="twitter:description" content="OpenVibe.Blog is the publishing home of the OpenVibe network: the official OpenVibe blog and blogs for every member — drafts, scheduled posts, media-rich writing, comments and feeds, with your OpenVibe account.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.blog/#site","url":"https://openvibe.blog/","name":"OpenVibe.Blog","description":"OpenVibe.Blog is the publishing home of the OpenVibe network: the official OpenVibe blog and blogs for every member — drafts, scheduled posts, media-rich writing, comments and feeds, with your OpenVibe account.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.blog/#page","url":"https://openvibe.blog/","name":"OpenVibe.Blog — Long-form, yours to keep.","description":"OpenVibe.Blog is the publishing home of the OpenVibe network: the official OpenVibe blog and blogs for every member — drafts, scheduled posts, media-rich writing, comments and feeds, with your OpenVibe account.","isPartOf":{"@id":"https://openvibe.blog/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Blog","item":"https://openvibe.blog/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#f472b6;--site-rgb:244,114,182}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="blog"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Blog</span></h1>
++ <div class="tag">Long-form, yours to keep.</div>
++ <p class="lead">OpenVibe.Blog is the publishing home of the OpenVibe network: the official OpenVibe blog and blogs for every member — drafts, scheduled posts, media-rich writing, comments and feeds, with your OpenVibe account.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.blog%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Blog will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i></div><b>The OpenVibe blog</b><span>Release notes, network updates and the story of the project.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i></div><b>Your blog</b><span>A blog for every account: drafts, tags, media, scheduling.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i></div><b>Comments &amp; feeds</b><span>Discussion through OpenVibe.Community; RSS for everyone.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i></div><b>Themes that follow you</b><span>Your network theme is your blog theme, if you want it to be.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live/updates"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Updates on OpenVibe.Live</b><span>What shipped, as it ships.</span><span class="go">openvibe.live/updates →</span></a>
++ <a class="card" href="https://openvibe.community/pastes"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Pastes</b><span>Share text and code today on OpenVibe.Community.</span><span class="go">openvibe.community/pastes →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="blog"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'blog', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Blog' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'blog', variant: 'full', links: [{ heading: 'OpenVibe.Blog', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.blog%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.blog/manifest.webmanifest b/dist/openvibe.blog/manifest.webmanifest
nnew file mode 100644
iindex 0000000..7f71f49
---- /dev/null
++++ b/dist/openvibe.blog/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Blog",
++ "short_name": "Blog",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#f472b6",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.blog/robots.txt b/dist/openvibe.blog/robots.txt
nnew file mode 100644
iindex 0000000..0b1397b
---- /dev/null
++++ b/dist/openvibe.blog/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.blog/sitemap.xml
ddiff --git a/dist/openvibe.blog/sitemap.xml b/dist/openvibe.blog/sitemap.xml
nnew file mode 100644
iindex 0000000..d360ce7
---- /dev/null
++++ b/dist/openvibe.blog/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.blog/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.chat/index.html b/dist/openvibe.chat/index.html
nnew file mode 100644
iindex 0000000..bc7bc98
---- /dev/null
++++ b/dist/openvibe.chat/index.html
@@@ -0,0 +1,167 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Chat — One chat for the whole network.</title>
++<meta name="description" content="OpenVibe.Chat is the communication layer of the OpenVibe network: global rooms, stream chat, direct messages, group rooms, voice calls and text-to-speech — one identity, every conversation.">
++<meta name="keywords" content="openvibe chat, community chat, voice rooms, direct messages, free speech chat">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#a78bfa">
++<link rel="canonical" href="https://openvibe.chat/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.chat/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Chat">
++<meta property="og:url" content="https://openvibe.chat/">
++<meta property="og:title" content="OpenVibe.Chat — One chat for the whole network.">
++<meta property="og:description" content="OpenVibe.Chat is the communication layer of the OpenVibe network: global rooms, stream chat, direct messages, group rooms, voice calls and text-to-speech — one identity, every conversation.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Chat — One chat for the whole network.">
++<meta name="twitter:description" content="OpenVibe.Chat is the communication layer of the OpenVibe network: global rooms, stream chat, direct messages, group rooms, voice calls and text-to-speech — one identity, every conversation.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.chat/#site","url":"https://openvibe.chat/","name":"OpenVibe.Chat","description":"OpenVibe.Chat is the communication layer of the OpenVibe network: global rooms, stream chat, direct messages, group rooms, voice calls and text-to-speech — one identity, every conversation.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.chat/#page","url":"https://openvibe.chat/","name":"OpenVibe.Chat — One chat for the whole network.","description":"OpenVibe.Chat is the communication layer of the OpenVibe network: global rooms, stream chat, direct messages, group rooms, voice calls and text-to-speech — one identity, every conversation.","isPartOf":{"@id":"https://openvibe.chat/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Chat","item":"https://openvibe.chat/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#a78bfa;--site-rgb:167,139,250}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-comments" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="chat"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Chat</span></h1>
++ <div class="tag">One chat for the whole network.</div>
++ <p class="lead">OpenVibe.Chat is the communication layer of the OpenVibe network: global rooms, stream chat, direct messages, group rooms, voice calls and text-to-speech — one identity, every conversation.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.chat%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Chat will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-comments" aria-hidden="true"></i></div><b>Global rooms</b><span>Rooms that span every OpenVibe site, with the same moderation tools everywhere.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-comments" aria-hidden="true"></i></div><b>Direct messages</b><span>DMs and group rooms tied to your OpenVibe account, not to one website.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-comments" aria-hidden="true"></i></div><b>Calls &amp; voice</b><span>Voice rooms and streamer-to-viewer calls, the same engine Live uses today.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-comments" aria-hidden="true"></i></div><b>TTS &amp; audio queues</b><span>Text-to-speech, soundboards and audio queues for streams and rooms.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live/chat"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Chat on OpenVibe.Live</b><span>The global chat is already live there — same account, same rules.</span><span class="go">openvibe.live/chat →</span></a>
++ <a class="card" href="https://openvibe.live/chat"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Voice channels</b><span>Voice rooms run inside Live&#39;s chat today.</span><span class="go">openvibe.live/chat →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="chat"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'chat', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Chat' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'chat', variant: 'full', links: [{ heading: 'OpenVibe.Chat', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.chat%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.chat/manifest.webmanifest b/dist/openvibe.chat/manifest.webmanifest
nnew file mode 100644
iindex 0000000..0e16f5e
---- /dev/null
++++ b/dist/openvibe.chat/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Chat",
++ "short_name": "Chat",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#a78bfa",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.chat/robots.txt b/dist/openvibe.chat/robots.txt
nnew file mode 100644
iindex 0000000..3e22df9
---- /dev/null
++++ b/dist/openvibe.chat/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.chat/sitemap.xml
ddiff --git a/dist/openvibe.chat/sitemap.xml b/dist/openvibe.chat/sitemap.xml
nnew file mode 100644
iindex 0000000..76b9374
---- /dev/null
++++ b/dist/openvibe.chat/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.chat/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.codes/index.html b/dist/openvibe.codes/index.html
nnew file mode 100644
iindex 0000000..40c7a82
---- /dev/null
++++ b/dist/openvibe.codes/index.html
@@@ -0,0 +1,168 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Codes — Build on OpenVibe.</title>
++<meta name="description" content="OpenVibe.Codes is the developer portal of the OpenVibe network: API and SDK documentation, the service and capability registry, event schemas, mod publishing, starter templates and vibe-coding sessions.">
++<meta name="keywords" content="openvibe api, openvibe sdk, developer portal, open source streaming api, mods">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#22d3ee">
++<link rel="canonical" href="https://openvibe.codes/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.codes/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Codes">
++<meta property="og:url" content="https://openvibe.codes/">
++<meta property="og:title" content="OpenVibe.Codes — Build on OpenVibe.">
++<meta property="og:description" content="OpenVibe.Codes is the developer portal of the OpenVibe network: API and SDK documentation, the service and capability registry, event schemas, mod publishing, starter templates and vibe-coding sessions.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Codes — Build on OpenVibe.">
++<meta name="twitter:description" content="OpenVibe.Codes is the developer portal of the OpenVibe network: API and SDK documentation, the service and capability registry, event schemas, mod publishing, starter templates and vibe-coding sessions.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.codes/#site","url":"https://openvibe.codes/","name":"OpenVibe.Codes","description":"OpenVibe.Codes is the developer portal of the OpenVibe network: API and SDK documentation, the service and capability registry, event schemas, mod publishing, starter templates and vibe-coding sessions.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.codes/#page","url":"https://openvibe.codes/","name":"OpenVibe.Codes — Build on OpenVibe.","description":"OpenVibe.Codes is the developer portal of the OpenVibe network: API and SDK documentation, the service and capability registry, event schemas, mod publishing, starter templates and vibe-coding sessions.","isPartOf":{"@id":"https://openvibe.codes/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Codes","item":"https://openvibe.codes/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#22d3ee;--site-rgb:34,211,238}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-code" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="codes"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Codes</span></h1>
++ <div class="tag">Build on OpenVibe.</div>
++ <p class="lead">OpenVibe.Codes is the developer portal of the OpenVibe network: API and SDK documentation, the service and capability registry, event schemas, mod publishing, starter templates and vibe-coding sessions.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.codes%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Codes will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-code" aria-hidden="true"></i></div><b>API &amp; SDK docs</b><span>One place for every OpenVibe API: identity, media, chat, live, community.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-code" aria-hidden="true"></i></div><b>Contracts &amp; events</b><span>Service manifests, capability schemas and the event backbone, documented.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-code" aria-hidden="true"></i></div><b>Mods &amp; templates</b><span>Publish mods and bots, start from templates, ship to the network.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-code" aria-hidden="true"></i></div><b>Vibe-coding</b><span>Publish coding sessions and let people build alongside you.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://github.com/OpenVibers"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>OpenVibe on GitHub</b><span>Every OpenVibe service is open source. Read, fork, contribute.</span><span class="go">github.com/OpenVibers →</span></a>
++ <a class="card" href="https://openvibe.live/documentation"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>WHIP &amp; streaming docs</b><span>The streaming API and ingest docs live on OpenVibe.Live today.</span><span class="go">openvibe.live/documentation →</span></a>
++ <a class="card" href="https://dev.openvibe.tools"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Dev tools</b><span>Formatters, encoders and validators on OpenVibe.Tools.</span><span class="go">dev.openvibe.tools →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="codes"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'codes', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Codes' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'codes', variant: 'full', links: [{ heading: 'OpenVibe.Codes', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.codes%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.codes/manifest.webmanifest b/dist/openvibe.codes/manifest.webmanifest
nnew file mode 100644
iindex 0000000..fd6fd7a
---- /dev/null
++++ b/dist/openvibe.codes/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Codes",
++ "short_name": "Codes",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#22d3ee",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.codes/robots.txt b/dist/openvibe.codes/robots.txt
nnew file mode 100644
iindex 0000000..b25175d
---- /dev/null
++++ b/dist/openvibe.codes/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.codes/sitemap.xml
ddiff --git a/dist/openvibe.codes/sitemap.xml b/dist/openvibe.codes/sitemap.xml
nnew file mode 100644
iindex 0000000..66ee7a9
---- /dev/null
++++ b/dist/openvibe.codes/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.codes/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.coupons/index.html b/dist/openvibe.coupons/index.html
nnew file mode 100644
iindex 0000000..9594090
---- /dev/null
++++ b/dist/openvibe.coupons/index.html
@@@ -0,0 +1,166 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Coupons — Codes that actually work.</title>
++<meta name="description" content="OpenVibe.Coupons is community-checked coupon discovery: codes matched to stores, validity reported by real people, expirations tracked, and a browser helper on the way.">
++<meta name="keywords" content="openvibe coupons, coupon codes, community coupons">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#fbbf24">
++<link rel="canonical" href="https://openvibe.coupons/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.coupons/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Coupons">
++<meta property="og:url" content="https://openvibe.coupons/">
++<meta property="og:title" content="OpenVibe.Coupons — Codes that actually work.">
++<meta property="og:description" content="OpenVibe.Coupons is community-checked coupon discovery: codes matched to stores, validity reported by real people, expirations tracked, and a browser helper on the way.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Coupons — Codes that actually work.">
++<meta name="twitter:description" content="OpenVibe.Coupons is community-checked coupon discovery: codes matched to stores, validity reported by real people, expirations tracked, and a browser helper on the way.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.coupons/#site","url":"https://openvibe.coupons/","name":"OpenVibe.Coupons","description":"OpenVibe.Coupons is community-checked coupon discovery: codes matched to stores, validity reported by real people, expirations tracked, and a browser helper on the way.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.coupons/#page","url":"https://openvibe.coupons/","name":"OpenVibe.Coupons — Codes that actually work.","description":"OpenVibe.Coupons is community-checked coupon discovery: codes matched to stores, validity reported by real people, expirations tracked, and a browser helper on the way.","isPartOf":{"@id":"https://openvibe.coupons/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Coupons","item":"https://openvibe.coupons/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#fbbf24;--site-rgb:251,191,36}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-ticket" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="coupons"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Coupons</span></h1>
++ <div class="tag">Codes that actually work.</div>
++ <p class="lead">OpenVibe.Coupons is community-checked coupon discovery: codes matched to stores, validity reported by real people, expirations tracked, and a browser helper on the way.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.coupons%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Coupons will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-ticket" aria-hidden="true"></i></div><b>Checked by people</b><span>Codes that worked, codes that didn&#39;t, reported honestly.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-ticket" aria-hidden="true"></i></div><b>Store matching</b><span>The right codes for the store you are on.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-ticket" aria-hidden="true"></i></div><b>Expiry tracking</b><span>Dead codes go away.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-ticket" aria-hidden="true"></i></div><b>Browser helper</b><span>Apply codes where you shop — coming with the site.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.deals"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Deals</b><span>Deal discovery is the sibling of this room.</span><span class="go">openvibe.deals →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="coupons"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'coupons', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Coupons' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'coupons', variant: 'full', links: [{ heading: 'OpenVibe.Coupons', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.coupons%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.coupons/manifest.webmanifest b/dist/openvibe.coupons/manifest.webmanifest
nnew file mode 100644
iindex 0000000..f8764b9
---- /dev/null
++++ b/dist/openvibe.coupons/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Coupons",
++ "short_name": "Coupons",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#fbbf24",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.coupons/robots.txt b/dist/openvibe.coupons/robots.txt
nnew file mode 100644
iindex 0000000..b49d97d
---- /dev/null
++++ b/dist/openvibe.coupons/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.coupons/sitemap.xml
ddiff --git a/dist/openvibe.coupons/sitemap.xml b/dist/openvibe.coupons/sitemap.xml
nnew file mode 100644
iindex 0000000..f8b0b8c
---- /dev/null
++++ b/dist/openvibe.coupons/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.coupons/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.deals/index.html b/dist/openvibe.deals/index.html
nnew file mode 100644
iindex 0000000..8dbdcdf
---- /dev/null
++++ b/dist/openvibe.deals/index.html
@@@ -0,0 +1,166 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Deals — Deals worth seeing.</title>
++<meta name="description" content="OpenVibe.Deals is community deal discovery for the OpenVibe network: deals people vote on, hotness that reflects real interest, keyword alerts, price comparisons and honest discussion.">
++<meta name="keywords" content="openvibe deals, community deals, deal alerts">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#f97316">
++<link rel="canonical" href="https://openvibe.deals/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.deals/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Deals">
++<meta property="og:url" content="https://openvibe.deals/">
++<meta property="og:title" content="OpenVibe.Deals — Deals worth seeing.">
++<meta property="og:description" content="OpenVibe.Deals is community deal discovery for the OpenVibe network: deals people vote on, hotness that reflects real interest, keyword alerts, price comparisons and honest discussion.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Deals — Deals worth seeing.">
++<meta name="twitter:description" content="OpenVibe.Deals is community deal discovery for the OpenVibe network: deals people vote on, hotness that reflects real interest, keyword alerts, price comparisons and honest discussion.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.deals/#site","url":"https://openvibe.deals/","name":"OpenVibe.Deals","description":"OpenVibe.Deals is community deal discovery for the OpenVibe network: deals people vote on, hotness that reflects real interest, keyword alerts, price comparisons and honest discussion.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.deals/#page","url":"https://openvibe.deals/","name":"OpenVibe.Deals — Deals worth seeing.","description":"OpenVibe.Deals is community deal discovery for the OpenVibe network: deals people vote on, hotness that reflects real interest, keyword alerts, price comparisons and honest discussion.","isPartOf":{"@id":"https://openvibe.deals/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Deals","item":"https://openvibe.deals/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#f97316;--site-rgb:249,115,22}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-tags" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="deals"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Deals</span></h1>
++ <div class="tag">Deals worth seeing.</div>
++ <p class="lead">OpenVibe.Deals is community deal discovery for the OpenVibe network: deals people vote on, hotness that reflects real interest, keyword alerts, price comparisons and honest discussion.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.deals%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Deals will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-tags" aria-hidden="true"></i></div><b>Voted, not paid for</b><span>Deals rise because people like them.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-tags" aria-hidden="true"></i></div><b>Alerts</b><span>Tell it what you want; it tells you when it is cheap.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-tags" aria-hidden="true"></i></div><b>Compare</b><span>Summaries and comparisons, with sources.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-tags" aria-hidden="true"></i></div><b>Discuss</b><span>Threads through OpenVibe.Community.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.coupons"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Coupons</b><span>The coupon room is the sibling of this one.</span><span class="go">openvibe.coupons →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="deals"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'deals', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Deals' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'deals', variant: 'full', links: [{ heading: 'OpenVibe.Deals', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.deals%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.deals/manifest.webmanifest b/dist/openvibe.deals/manifest.webmanifest
nnew file mode 100644
iindex 0000000..c135d91
---- /dev/null
++++ b/dist/openvibe.deals/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Deals",
++ "short_name": "Deals",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#f97316",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.deals/robots.txt b/dist/openvibe.deals/robots.txt
nnew file mode 100644
iindex 0000000..eb8c30b
---- /dev/null
++++ b/dist/openvibe.deals/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.deals/sitemap.xml
ddiff --git a/dist/openvibe.deals/sitemap.xml b/dist/openvibe.deals/sitemap.xml
nnew file mode 100644
iindex 0000000..945bb23
---- /dev/null
++++ b/dist/openvibe.deals/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.deals/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.host/index.html b/dist/openvibe.host/index.html
nnew file mode 100644
iindex 0000000..8500e84
---- /dev/null
++++ b/dist/openvibe.host/index.html
@@@ -0,0 +1,166 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Host — Run it yourself.</title>
++<meta name="description" content="OpenVibe.Host is the hosting and deployment surface of the OpenVibe network: deploy OpenVibe services, bots, mods and static sites, with TLS, DNS and logs handled for you.">
++<meta name="keywords" content="openvibe host, hosting, deployment, self-hosting openvibe">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#94a3b8">
++<link rel="canonical" href="https://openvibe.host/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.host/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Host">
++<meta property="og:url" content="https://openvibe.host/">
++<meta property="og:title" content="OpenVibe.Host — Run it yourself.">
++<meta property="og:description" content="OpenVibe.Host is the hosting and deployment surface of the OpenVibe network: deploy OpenVibe services, bots, mods and static sites, with TLS, DNS and logs handled for you.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Host — Run it yourself.">
++<meta name="twitter:description" content="OpenVibe.Host is the hosting and deployment surface of the OpenVibe network: deploy OpenVibe services, bots, mods and static sites, with TLS, DNS and logs handled for you.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.host/#site","url":"https://openvibe.host/","name":"OpenVibe.Host","description":"OpenVibe.Host is the hosting and deployment surface of the OpenVibe network: deploy OpenVibe services, bots, mods and static sites, with TLS, DNS and logs handled for you.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.host/#page","url":"https://openvibe.host/","name":"OpenVibe.Host — Run it yourself.","description":"OpenVibe.Host is the hosting and deployment surface of the OpenVibe network: deploy OpenVibe services, bots, mods and static sites, with TLS, DNS and logs handled for you.","isPartOf":{"@id":"https://openvibe.host/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Host","item":"https://openvibe.host/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#94a3b8;--site-rgb:148,163,184}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-server" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="host"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Host</span></h1>
++ <div class="tag">Run it yourself.</div>
++ <p class="lead">OpenVibe.Host is the hosting and deployment surface of the OpenVibe network: deploy OpenVibe services, bots, mods and static sites, with TLS, DNS and logs handled for you.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.host%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Host will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-server" aria-hidden="true"></i></div><b>Service hosting</b><span>Every OpenVibe service, deployable in one step.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-server" aria-hidden="true"></i></div><b>Bots &amp; mods</b><span>Host your bot or mod next to the network it talks to.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-server" aria-hidden="true"></i></div><b>Static sites</b><span>A folder in, a domain out, with TLS.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-server" aria-hidden="true"></i></div><b>Open source</b><span>The same deploy tooling the network runs on.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://github.com/OpenVibers"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Deploy docs</b><span>Every service ships its own deploy scripts on GitHub.</span><span class="go">github.com/OpenVibers →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="host"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'host', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Host' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'host', variant: 'full', links: [{ heading: 'OpenVibe.Host', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.host%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.host/manifest.webmanifest b/dist/openvibe.host/manifest.webmanifest
nnew file mode 100644
iindex 0000000..a407883
---- /dev/null
++++ b/dist/openvibe.host/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Host",
++ "short_name": "Host",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#94a3b8",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.host/robots.txt b/dist/openvibe.host/robots.txt
nnew file mode 100644
iindex 0000000..8238e87
---- /dev/null
++++ b/dist/openvibe.host/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.host/sitemap.xml
ddiff --git a/dist/openvibe.host/sitemap.xml b/dist/openvibe.host/sitemap.xml
nnew file mode 100644
iindex 0000000..3f8f59b
---- /dev/null
++++ b/dist/openvibe.host/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.host/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.news/index.html b/dist/openvibe.news/index.html
nnew file mode 100644
iindex 0000000..00a1a29
---- /dev/null
++++ b/dist/openvibe.news/index.html
@@@ -0,0 +1,166 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.News — Sourced. Summarised. Many angles.</title>
++<meta name="description" content="OpenVibe.News aggregates the news with transparency: sourced stories, summaries that show their sources, multiple angles side by side, topic pages and framing you control — not an algorithm you can&#39;t see.">
++<meta name="keywords" content="openvibe news, transparent news, news aggregation, multiple perspectives">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#fb923c">
++<link rel="canonical" href="https://openvibe.news/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.news/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.News">
++<meta property="og:url" content="https://openvibe.news/">
++<meta property="og:title" content="OpenVibe.News — Sourced. Summarised. Many angles.">
++<meta property="og:description" content="OpenVibe.News aggregates the news with transparency: sourced stories, summaries that show their sources, multiple angles side by side, topic pages and framing you control — not an algorithm you can&#39;t see.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.News — Sourced. Summarised. Many angles.">
++<meta name="twitter:description" content="OpenVibe.News aggregates the news with transparency: sourced stories, summaries that show their sources, multiple angles side by side, topic pages and framing you control — not an algorithm you can&#39;t see.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.news/#site","url":"https://openvibe.news/","name":"OpenVibe.News","description":"OpenVibe.News aggregates the news with transparency: sourced stories, summaries that show their sources, multiple angles side by side, topic pages and framing you control — not an algorithm you can't see.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.news/#page","url":"https://openvibe.news/","name":"OpenVibe.News — Sourced. Summarised. Many angles.","description":"OpenVibe.News aggregates the news with transparency: sourced stories, summaries that show their sources, multiple angles side by side, topic pages and framing you control — not an algorithm you can't see.","isPartOf":{"@id":"https://openvibe.news/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.News","item":"https://openvibe.news/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#fb923c;--site-rgb:251,146,60}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-newspaper" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="news"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">News</span></h1>
++ <div class="tag">Sourced. Summarised. Many angles.</div>
++ <p class="lead">OpenVibe.News aggregates the news with transparency: sourced stories, summaries that show their sources, multiple angles side by side, topic pages and framing you control — not an algorithm you can&#39;t see.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.news%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.News will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-newspaper" aria-hidden="true"></i></div><b>Sources first</b><span>Every summary links to what it was built from.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-newspaper" aria-hidden="true"></i></div><b>Many angles</b><span>Read the same story from several perspectives, side by side.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-newspaper" aria-hidden="true"></i></div><b>Your framing</b><span>You choose the lens; nothing is chosen for you silently.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-newspaper" aria-hidden="true"></i></div><b>Topics</b><span>Follow topics across sources, with your OpenVibe account.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live/updates"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Network updates</b><span>What is happening across OpenVibe.</span><span class="go">openvibe.live/updates →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="news"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'news', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.News' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'news', variant: 'full', links: [{ heading: 'OpenVibe.News', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.news%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.news/manifest.webmanifest b/dist/openvibe.news/manifest.webmanifest
nnew file mode 100644
iindex 0000000..8a393fd
---- /dev/null
++++ b/dist/openvibe.news/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.News",
++ "short_name": "News",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#fb923c",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.news/robots.txt b/dist/openvibe.news/robots.txt
nnew file mode 100644
iindex 0000000..86d1249
---- /dev/null
++++ b/dist/openvibe.news/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.news/sitemap.xml
ddiff --git a/dist/openvibe.news/sitemap.xml b/dist/openvibe.news/sitemap.xml
nnew file mode 100644
iindex 0000000..a444241
---- /dev/null
++++ b/dist/openvibe.news/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.news/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.reviews/index.html b/dist/openvibe.reviews/index.html
nnew file mode 100644
iindex 0000000..e154e6e
---- /dev/null
++++ b/dist/openvibe.reviews/index.html
@@@ -0,0 +1,166 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Reviews — What people actually say.</title>
++<meta name="description" content="OpenVibe.Reviews gathers what people say about products, services, employers, hosts and communities across many sources — with provenance, without fake ratings — and lets the community discuss it.">
++<meta name="keywords" content="openvibe reviews, review aggregation, honest reviews">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#facc15">
++<link rel="canonical" href="https://openvibe.reviews/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.reviews/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Reviews">
++<meta property="og:url" content="https://openvibe.reviews/">
++<meta property="og:title" content="OpenVibe.Reviews — What people actually say.">
++<meta property="og:description" content="OpenVibe.Reviews gathers what people say about products, services, employers, hosts and communities across many sources — with provenance, without fake ratings — and lets the community discuss it.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Reviews — What people actually say.">
++<meta name="twitter:description" content="OpenVibe.Reviews gathers what people say about products, services, employers, hosts and communities across many sources — with provenance, without fake ratings — and lets the community discuss it.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.reviews/#site","url":"https://openvibe.reviews/","name":"OpenVibe.Reviews","description":"OpenVibe.Reviews gathers what people say about products, services, employers, hosts and communities across many sources — with provenance, without fake ratings — and lets the community discuss it.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.reviews/#page","url":"https://openvibe.reviews/","name":"OpenVibe.Reviews — What people actually say.","description":"OpenVibe.Reviews gathers what people say about products, services, employers, hosts and communities across many sources — with provenance, without fake ratings — and lets the community discuss it.","isPartOf":{"@id":"https://openvibe.reviews/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Reviews","item":"https://openvibe.reviews/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#facc15;--site-rgb:250,204,21}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="reviews"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Reviews</span></h1>
++ <div class="tag">What people actually say.</div>
++ <p class="lead">OpenVibe.Reviews gathers what people say about products, services, employers, hosts and communities across many sources — with provenance, without fake ratings — and lets the community discuss it.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.reviews%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Reviews will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i></div><b>Entity pages</b><span>One page per product, service or place, built from many sources.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i></div><b>Provenance</b><span>Every quote links back to where it was said.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i></div><b>No fake ratings</b><span>Summaries, not invented stars.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i></div><b>Discussion</b><span>Community threads through OpenVibe.Community.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Talk about it</b><span>Community threads are the first stop.</span><span class="go">openvibe.community →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="reviews"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'reviews', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Reviews' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'reviews', variant: 'full', links: [{ heading: 'OpenVibe.Reviews', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.reviews%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.reviews/manifest.webmanifest b/dist/openvibe.reviews/manifest.webmanifest
nnew file mode 100644
iindex 0000000..9038b6a
---- /dev/null
++++ b/dist/openvibe.reviews/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Reviews",
++ "short_name": "Reviews",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#facc15",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.reviews/robots.txt b/dist/openvibe.reviews/robots.txt
nnew file mode 100644
iindex 0000000..cb93f51
---- /dev/null
++++ b/dist/openvibe.reviews/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.reviews/sitemap.xml
ddiff --git a/dist/openvibe.reviews/sitemap.xml b/dist/openvibe.reviews/sitemap.xml
nnew file mode 100644
iindex 0000000..00942ff
---- /dev/null
++++ b/dist/openvibe.reviews/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.reviews/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.tips/index.html b/dist/openvibe.tips/index.html
nnew file mode 100644
iindex 0000000..78a1213
---- /dev/null
++++ b/dist/openvibe.tips/index.html
@@@ -0,0 +1,166 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Tips — Support the people you watch.</title>
++<meta name="description" content="OpenVibe.Tips is the tipping and alerts layer of the OpenVibe network: tips, donation goals, superchats, paid text-to-speech and media requests, with alert overlays for creators.">
++<meta name="keywords" content="openvibe tips, tip streamers, donation alerts, superchat">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#4ade80">
++<link rel="canonical" href="https://openvibe.tips/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.tips/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Tips">
++<meta property="og:url" content="https://openvibe.tips/">
++<meta property="og:title" content="OpenVibe.Tips — Support the people you watch.">
++<meta property="og:description" content="OpenVibe.Tips is the tipping and alerts layer of the OpenVibe network: tips, donation goals, superchats, paid text-to-speech and media requests, with alert overlays for creators.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Tips — Support the people you watch.">
++<meta name="twitter:description" content="OpenVibe.Tips is the tipping and alerts layer of the OpenVibe network: tips, donation goals, superchats, paid text-to-speech and media requests, with alert overlays for creators.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.tips/#site","url":"https://openvibe.tips/","name":"OpenVibe.Tips","description":"OpenVibe.Tips is the tipping and alerts layer of the OpenVibe network: tips, donation goals, superchats, paid text-to-speech and media requests, with alert overlays for creators.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.tips/#page","url":"https://openvibe.tips/","name":"OpenVibe.Tips — Support the people you watch.","description":"OpenVibe.Tips is the tipping and alerts layer of the OpenVibe network: tips, donation goals, superchats, paid text-to-speech and media requests, with alert overlays for creators.","isPartOf":{"@id":"https://openvibe.tips/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Tips","item":"https://openvibe.tips/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#4ade80;--site-rgb:74,222,128}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="tips"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Tips</span></h1>
++ <div class="tag">Support the people you watch.</div>
++ <p class="lead">OpenVibe.Tips is the tipping and alerts layer of the OpenVibe network: tips, donation goals, superchats, paid text-to-speech and media requests, with alert overlays for creators.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.tips%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Tips will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i></div><b>Tips &amp; goals</b><span>Tip a creator, fund a goal, see it land on stream.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i></div><b>Superchat &amp; TTS</b><span>Paid messages read out on stream, through OpenVibe.Chat.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i></div><b>Alert overlays</b><span>Overlays for OBS and the browser, themed with the network.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i></div><b>One ledger</b><span>Every transaction on the network&#39;s own ledger, visible to you.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Tip with Vibes on OpenVibe.Live</b><span>Tips already work on Live today.</span><span class="go">openvibe.live →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="tips"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'tips', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Tips' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'tips', variant: 'full', links: [{ heading: 'OpenVibe.Tips', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.tips%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.tips/manifest.webmanifest b/dist/openvibe.tips/manifest.webmanifest
nnew file mode 100644
iindex 0000000..fdbccd2
---- /dev/null
++++ b/dist/openvibe.tips/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Tips",
++ "short_name": "Tips",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#4ade80",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.tips/robots.txt b/dist/openvibe.tips/robots.txt
nnew file mode 100644
iindex 0000000..147ae5f
---- /dev/null
++++ b/dist/openvibe.tips/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.tips/sitemap.xml
ddiff --git a/dist/openvibe.tips/sitemap.xml b/dist/openvibe.tips/sitemap.xml
nnew file mode 100644
iindex 0000000..0a57027
---- /dev/null
++++ b/dist/openvibe.tips/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.tips/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.trade/index.html b/dist/openvibe.trade/index.html
nnew file mode 100644
iindex 0000000..bda0b44
---- /dev/null
++++ b/dist/openvibe.trade/index.html
@@@ -0,0 +1,166 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Trade — Watch, discuss, decide.</title>
++<meta name="description" content="OpenVibe.Trade is the market intelligence room of the OpenVibe network: watchlists, alerts, summaries and community discussion for markets, collectibles and deals — information and tools, never advice.">
++<meta name="keywords" content="openvibe trade, watchlists, market alerts, community trading tools">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#60a5fa">
++<link rel="canonical" href="https://openvibe.trade/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.trade/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Trade">
++<meta property="og:url" content="https://openvibe.trade/">
++<meta property="og:title" content="OpenVibe.Trade — Watch, discuss, decide.">
++<meta property="og:description" content="OpenVibe.Trade is the market intelligence room of the OpenVibe network: watchlists, alerts, summaries and community discussion for markets, collectibles and deals — information and tools, never advice.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Trade — Watch, discuss, decide.">
++<meta name="twitter:description" content="OpenVibe.Trade is the market intelligence room of the OpenVibe network: watchlists, alerts, summaries and community discussion for markets, collectibles and deals — information and tools, never advice.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.trade/#site","url":"https://openvibe.trade/","name":"OpenVibe.Trade","description":"OpenVibe.Trade is the market intelligence room of the OpenVibe network: watchlists, alerts, summaries and community discussion for markets, collectibles and deals — information and tools, never advice.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.trade/#page","url":"https://openvibe.trade/","name":"OpenVibe.Trade — Watch, discuss, decide.","description":"OpenVibe.Trade is the market intelligence room of the OpenVibe network: watchlists, alerts, summaries and community discussion for markets, collectibles and deals — information and tools, never advice.","isPartOf":{"@id":"https://openvibe.trade/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Trade","item":"https://openvibe.trade/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#60a5fa;--site-rgb:96,165,250}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-chart-line" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="trade"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Trade</span></h1>
++ <div class="tag">Watch, discuss, decide.</div>
++ <p class="lead">OpenVibe.Trade is the market intelligence room of the OpenVibe network: watchlists, alerts, summaries and community discussion for markets, collectibles and deals — information and tools, never advice.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.trade%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Trade will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-chart-line" aria-hidden="true"></i></div><b>Watchlists &amp; alerts</b><span>Track what you care about, get told when it moves.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-chart-line" aria-hidden="true"></i></div><b>Summaries</b><span>What happened and why, with sources.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-chart-line" aria-hidden="true"></i></div><b>Community</b><span>Discuss with people, not bots.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-chart-line" aria-hidden="true"></i></div><b>Not advice</b><span>Tools and information only — always labelled as such.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.deals"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Deals</b><span>Deal discovery is the sibling room.</span><span class="go">openvibe.deals →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="trade"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'trade', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Trade' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'trade', variant: 'full', links: [{ heading: 'OpenVibe.Trade', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.trade%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.trade/manifest.webmanifest b/dist/openvibe.trade/manifest.webmanifest
nnew file mode 100644
iindex 0000000..2d51e35
---- /dev/null
++++ b/dist/openvibe.trade/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Trade",
++ "short_name": "Trade",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#60a5fa",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.trade/robots.txt b/dist/openvibe.trade/robots.txt
nnew file mode 100644
iindex 0000000..6bc0024
---- /dev/null
++++ b/dist/openvibe.trade/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.trade/sitemap.xml
ddiff --git a/dist/openvibe.trade/sitemap.xml b/dist/openvibe.trade/sitemap.xml
nnew file mode 100644
iindex 0000000..0cfae49
---- /dev/null
++++ b/dist/openvibe.trade/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.trade/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.vip/index.html b/dist/openvibe.vip/index.html
nnew file mode 100644
iindex 0000000..abcd7b6
---- /dev/null
++++ b/dist/openvibe.vip/index.html
@@@ -0,0 +1,166 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.VIP — Memberships, network-wide.</title>
++<meta name="description" content="OpenVibe.VIP is the membership layer of the OpenVibe network: creator memberships, channel subscriptions, VIP tiers and perks that unlock across Live, Community, Blog and more.">
++<meta name="keywords" content="openvibe vip, creator memberships, subscriptions">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#e879f9">
++<link rel="canonical" href="https://openvibe.vip/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.vip/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.VIP">
++<meta property="og:url" content="https://openvibe.vip/">
++<meta property="og:title" content="OpenVibe.VIP — Memberships, network-wide.">
++<meta property="og:description" content="OpenVibe.VIP is the membership layer of the OpenVibe network: creator memberships, channel subscriptions, VIP tiers and perks that unlock across Live, Community, Blog and more.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.VIP — Memberships, network-wide.">
++<meta name="twitter:description" content="OpenVibe.VIP is the membership layer of the OpenVibe network: creator memberships, channel subscriptions, VIP tiers and perks that unlock across Live, Community, Blog and more.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.vip/#site","url":"https://openvibe.vip/","name":"OpenVibe.VIP","description":"OpenVibe.VIP is the membership layer of the OpenVibe network: creator memberships, channel subscriptions, VIP tiers and perks that unlock across Live, Community, Blog and more.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.vip/#page","url":"https://openvibe.vip/","name":"OpenVibe.VIP — Memberships, network-wide.","description":"OpenVibe.VIP is the membership layer of the OpenVibe network: creator memberships, channel subscriptions, VIP tiers and perks that unlock across Live, Community, Blog and more.","isPartOf":{"@id":"https://openvibe.vip/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.VIP","item":"https://openvibe.vip/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#e879f9;--site-rgb:232,121,249}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-crown" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="vip"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">VIP</span></h1>
++ <div class="tag">Memberships, network-wide.</div>
++ <p class="lead">OpenVibe.VIP is the membership layer of the OpenVibe network: creator memberships, channel subscriptions, VIP tiers and perks that unlock across Live, Community, Blog and more.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.vip%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.VIP will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-crown" aria-hidden="true"></i></div><b>Creator memberships</b><span>Subscribe to the people you watch; perks follow you everywhere.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-crown" aria-hidden="true"></i></div><b>Network VIP</b><span>One membership that supports the whole network.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-crown" aria-hidden="true"></i></div><b>Perks</b><span>Badges, emotes, early access, gated posts — set by creators.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-crown" aria-hidden="true"></i></div><b>Transparent</b><span>What it costs and where it goes, in the open.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>Subscriptions on OpenVibe.Live</b><span>Channel subscriptions exist on Live today.</span><span class="go">openvibe.live →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.wiki/"><i class="fa-solid fa-book" aria-hidden="true"></i>OpenVibe.Wiki</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="vip"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'vip', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.VIP' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'vip', variant: 'full', links: [{ heading: 'OpenVibe.VIP', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.vip%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.vip/manifest.webmanifest b/dist/openvibe.vip/manifest.webmanifest
nnew file mode 100644
iindex 0000000..f6895b8
---- /dev/null
++++ b/dist/openvibe.vip/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.VIP",
++ "short_name": "VIP",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#e879f9",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.vip/robots.txt b/dist/openvibe.vip/robots.txt
nnew file mode 100644
iindex 0000000..f67079d
---- /dev/null
++++ b/dist/openvibe.vip/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.vip/sitemap.xml
ddiff --git a/dist/openvibe.vip/sitemap.xml b/dist/openvibe.vip/sitemap.xml
nnew file mode 100644
iindex 0000000..33f0623
---- /dev/null
++++ b/dist/openvibe.vip/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.vip/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/dist/openvibe.wiki/index.html b/dist/openvibe.wiki/index.html
nnew file mode 100644
iindex 0000000..be9a174
---- /dev/null
++++ b/dist/openvibe.wiki/index.html
@@@ -0,0 +1,166 @@
++<!DOCTYPE html>
++<html lang="en">
++<head>
++<meta charset="utf-8">
++<meta name="viewport" content="width=device-width, initial-scale=1">
++<title>OpenVibe.Wiki — Knowledge, with sources.</title>
++<meta name="description" content="OpenVibe.Wiki is the knowledge space of the OpenVibe network: wiki spaces you can build and edit together, source-backed and AI-assisted, with page trees, citations, media and discussion.">
++<meta name="keywords" content="openvibe wiki, community wiki, knowledge base">
++<meta name="robots" content="index, follow, max-image-preview:large">
++<meta name="theme-color" content="#34d399">
++<link rel="canonical" href="https://openvibe.wiki/">
++<link rel="icon" href="https://openvibe.network/assets/favicon.svg" type="image/svg+xml">
++<link rel="manifest" href="/manifest.webmanifest">
++<link rel="alternate" type="text/html" hreflang="en" href="https://openvibe.wiki/">
++<meta property="og:type" content="website">
++<meta property="og:site_name" content="OpenVibe.Wiki">
++<meta property="og:url" content="https://openvibe.wiki/">
++<meta property="og:title" content="OpenVibe.Wiki — Knowledge, with sources.">
++<meta property="og:description" content="OpenVibe.Wiki is the knowledge space of the OpenVibe network: wiki spaces you can build and edit together, source-backed and AI-assisted, with page trees, citations, media and discussion.">
++<meta property="og:image" content="https://openvibe.network/assets/logo-512.png">
++<meta property="og:image:alt" content="OpenVibe">
++<meta name="twitter:card" content="summary">
++<meta name="twitter:title" content="OpenVibe.Wiki — Knowledge, with sources.">
++<meta name="twitter:description" content="OpenVibe.Wiki is the knowledge space of the OpenVibe network: wiki spaces you can build and edit together, source-backed and AI-assisted, with page trees, citations, media and discussion.">
++<meta name="twitter:image" content="https://openvibe.network/assets/logo-512.png">
++<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://openvibe.wiki/#site","url":"https://openvibe.wiki/","name":"OpenVibe.Wiki","description":"OpenVibe.Wiki is the knowledge space of the OpenVibe network: wiki spaces you can build and edit together, source-backed and AI-assisted, with page trees, citations, media and discussion.","inLanguage":"en","publisher":{"@type":"Organization","@id":"https://openvibe.network/#org","name":"OpenVibe","url":"https://openvibe.network/","logo":"https://openvibe.network/assets/logo-512.png","sameAs":["https://github.com/OpenVibers","https://discord.gg/M6MuRUaeJj"]},"isPartOf":{"@type":"WebSite","@id":"https://openvibe.network/#site","name":"OpenVibe.Network","url":"https://openvibe.network/"}},{"@type":"WebPage","@id":"https://openvibe.wiki/#page","url":"https://openvibe.wiki/","name":"OpenVibe.Wiki — Knowledge, with sources.","description":"OpenVibe.Wiki is the knowledge space of the OpenVibe network: wiki spaces you can build and edit together, source-backed and AI-assisted, with page trees, citations, media and discussion.","isPartOf":{"@id":"https://openvibe.wiki/#site"},"datePublished":"2026-09-18","dateModified":"2026-09-18","breadcrumb":{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"OpenVibe","item":"https://openvibe.network/"},{"@type":"ListItem","position":2,"name":"OpenVibe.Wiki","item":"https://openvibe.wiki/"}]}}]}</script>
++<script>(function(){try{var raw=localStorage.getItem('ov_theme');if(!raw)return;var t=JSON.parse(raw),v=t&&t.variables;if(!v)return;var el=document.documentElement;for(var k in v)if(k.charAt(0)==='-')el.style.setProperty(k,v[k]);if(t.id)el.setAttribute('data-theme',t.id);}catch(_){}})();</script>
++<script src="https://openvibe.network/shared/theme-loader.js"></script>
++<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
++<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" media="print" onload="this.media='all'">
++<noscript><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"></noscript>
++<style>
++*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
++:root{--bg-primary:#0a0f1c;--bg-secondary:#101828;--bg-card:#131c2e;--bg-hover:#1c2a44;--border:#1f2d47;--text-primary:#e6edf7;--text-secondary:#96a7c2;--text-muted:#7386a3;--accent:#3b82f6;--accent-light:#60a5fa;--accent-rgb:59,130,246;--on-accent:#fff;--site:#34d399;--site-rgb:52,211,153}
++html{scroll-behavior:smooth}
++body{background:var(--bg-primary);color:var(--text-primary);font-family:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;min-height:100vh;display:flex;flex-direction:column;overflow-x:hidden}
++main{flex:1;position:relative}
++.orbs{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
++.orbs i{position:absolute;border-radius:50%;filter:blur(90px);opacity:.16;animation:drift 26s ease-in-out infinite alternate}
++.orbs i:nth-child(1){width:420px;height:420px;background:var(--site);top:-140px;left:-120px}
++.orbs i:nth-child(2){width:360px;height:360px;background:var(--accent);top:40%;right:-140px;animation-delay:-9s}
++.orbs i:nth-child(3){width:300px;height:300px;background:var(--site);bottom:-120px;left:38%;animation-delay:-17s}
++@keyframes drift{0%{transform:translate(0,0) scale(1)}50%{transform:translate(-26px,36px) scale(1.07)}100%{transform:translate(34px,-28px) scale(.95)}}
++.wrap{position:relative;z-index:1;max-width:1040px;margin:0 auto;padding:0 20px}
++.hero{padding:84px 0 44px;text-align:center}
++.hero .mark{display:inline-grid;place-items:center;width:84px;height:84px;border-radius:24px;background:rgba(var(--site-rgb),.12);border:1px solid rgba(var(--site-rgb),.35);color:var(--site);font-size:34px;margin-bottom:22px;box-shadow:0 20px 60px rgba(var(--site-rgb),.18);animation:rise .6s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge{display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:999px;border:1px solid var(--border);background:var(--bg-secondary);font-size:12px;font-weight:600;color:var(--text-secondary);letter-spacing:.3px;margin-bottom:22px;animation:rise .6s .05s cubic-bezier(.2,.8,.2,1) both}
++.hero .badge b{color:var(--site)}
++.hero h1{font-size:clamp(34px,6vw,58px);font-weight:800;letter-spacing:-1.4px;line-height:1.08;animation:rise .6s .1s cubic-bezier(.2,.8,.2,1) both}
++.hero h1 .d{color:var(--site)}
++.hero h1 .tld{color:var(--text-secondary)}
++.hero .tag{font-size:clamp(18px,2.6vw,24px);font-weight:600;color:var(--text-primary);margin:18px 0 10px;animation:rise .6s .16s cubic-bezier(.2,.8,.2,1) both}
++.hero p.lead{color:var(--text-secondary);font-size:16px;line-height:1.65;max-width:680px;margin:0 auto;animation:rise .6s .22s cubic-bezier(.2,.8,.2,1) both}
++.ctas{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:30px;animation:rise .6s .3s cubic-bezier(.2,.8,.2,1) both}
++.btn{display:inline-flex;align-items:center;gap:9px;padding:12px 20px;border-radius:12px;font-size:14px;font-weight:600;text-decoration:none;border:1px solid var(--border);color:var(--text-primary);background:var(--bg-secondary);transition:transform .15s,border-color .15s,box-shadow .15s}
++.btn:hover{transform:translateY(-1px);border-color:var(--site);box-shadow:0 10px 30px rgba(var(--site-rgb),.15)}
++.btn-primary{background:var(--site);border-color:var(--site);color:#0b0d10}
++.btn-primary:hover{filter:brightness(1.08)}
++@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
++section{padding:36px 0}
++h2{font-size:22px;font-weight:700;letter-spacing:-.3px;margin-bottom:6px}
++.lead2{color:var(--text-secondary);font-size:14px;margin-bottom:20px}
++.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:14px}
++.card{background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:20px;transition:transform .2s,border-color .2s,box-shadow .2s;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:8px}
++a.card:hover{transform:translateY(-3px);border-color:rgba(var(--site-rgb),.6);box-shadow:0 16px 40px rgba(0,0,0,.35)}
++.card .ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;background:rgba(var(--site-rgb),.12);color:var(--site);font-size:17px}
++.card b{font-size:15px}
++.card span{font-size:13px;color:var(--text-secondary);line-height:1.55}
++.card .go{margin-top:auto;font-size:12.5px;font-weight:600;color:var(--site)}
++.meanwhile .card .ic{background:rgba(var(--accent-rgb),.12);color:var(--accent-light)}
++.net .card .ic{background:var(--bg-hover);color:var(--text-primary)}
++.rooms{display:flex;flex-wrap:wrap;gap:8px}
++.rooms a{font-size:12.5px;padding:7px 12px;border-radius:999px;border:1px solid var(--border);color:var(--text-secondary);text-decoration:none;transition:all .15s;background:var(--bg-secondary)}
++.rooms a:hover{color:var(--text-primary);border-color:var(--site)}
++.rooms a i{margin-right:6px;opacity:.8}
++.strip{border:1px solid var(--border);border-radius:18px;background:var(--bg-secondary);padding:30px 26px;text-align:center;margin:10px 0 50px}
++.strip h3{font-size:19px;font-weight:700;margin:12px 0 8px}
++.strip p{font-size:14px;color:var(--text-secondary);max-width:600px;margin:0 auto 18px;line-height:1.6}
++.strip .ov-mark{width:44px;height:44px}
++@media (max-width:600px){.hero{padding-top:56px}.ctas .btn{width:100%;justify-content:center}}
++@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
++</style>
++</head>
++<body>
++<div class="orbs"><i></i><i></i><i></i></div>
++<div id="navbar-mount"></div>
++<main class="wrap">
++ <header class="hero">
++ <div class="mark"><i class="fa-solid fa-book" aria-hidden="true"></i></div>
++ <div class="badge"><span class="ov-mark" data-size="16" data-variant="wiki"></span> Part of the OpenVibe network · <b>opening soon</b></div>
++ <h1>OpenVibe<span class="d">.</span><span class="tld">Wiki</span></h1>
++ <div class="tag">Knowledge, with sources.</div>
++ <p class="lead">OpenVibe.Wiki is the knowledge space of the OpenVibe network: wiki spaces you can build and edit together, source-backed and AI-assisted, with page trees, citations, media and discussion.</p>
++ <div class="ctas">
++ <a class="btn btn-primary" href="https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.wiki%2F"><i class="fa-solid fa-right-to-bracket"></i> Sign in with OpenVibe</a>
++ <a class="btn" href="https://openvibe.network/#network"><i class="fa-solid fa-circle-nodes"></i> The whole network</a>
++ <a class="btn" href="https://discord.gg/M6MuRUaeJj" rel="noopener"><i class="fa-brands fa-discord"></i> Follow the build</a>
++ </div>
++ </header>
++
++ <section>
++ <h2>What OpenVibe.Wiki will be</h2>
++ <p class="lead2">Same account, same themes, same navbar as every other OpenVibe site — built in the open, run by its community.</p>
++ <div class="grid">
++ <div class="card"><div class="ic"><i class="fa-solid fa-book" aria-hidden="true"></i></div><b>Spaces</b><span>A wiki space per topic, game, community or project.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-book" aria-hidden="true"></i></div><b>Source-backed</b><span>Every generated page carries its sources; every edit is yours.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-book" aria-hidden="true"></i></div><b>Page trees &amp; history</b><span>Organise, revise, roll back.</span></div>
++ <div class="card"><div class="ic"><i class="fa-solid fa-book" aria-hidden="true"></i></div><b>Discussion</b><span>Talk pages through OpenVibe.Community.</span></div>
++ </div>
++ </section>
++
++ <section class="meanwhile">
++ <h2>Meanwhile, on the network</h2>
++ <p class="lead2">Most of this already exists somewhere on OpenVibe — start there today.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live/documentation"><div class="ic"><i class="fa-solid fa-arrow-up-right-from-square" aria-hidden="true"></i></div><b>OpenVibe documentation</b><span>The streaming docs are the first wiki-like space of the network.</span><span class="go">openvibe.live/documentation →</span></a>
++ </div>
++ </section>
++
++ <section class="net">
++ <h2>The OpenVibe network</h2>
++ <p class="lead2">One account for all of it. Sign in once and every site signs you in.</p>
++ <div class="grid">
++ <a class="card" href="https://openvibe.live"><div class="ic"><i class="fa-solid fa-tower-broadcast" aria-hidden="true"></i></div><b>OpenVibe.Live</b><span>Go live, chat, clip, restream</span><span class="go">openvibe.live →</span></a>
++ <a class="card" href="https://openvibe.tools"><div class="ic"><i class="fa-solid fa-screwdriver-wrench" aria-hidden="true"></i></div><b>OpenVibe.Tools</b><span>Hundreds of online tools</span><span class="go">openvibe.tools →</span></a>
++ <a class="card" href="https://openvibe.community"><div class="ic"><i class="fa-solid fa-people-group" aria-hidden="true"></i></div><b>OpenVibe.Community</b><span>Pastes, posts, people</span><span class="go">openvibe.community →</span></a>
++ <a class="card" href="https://openvibe.games"><div class="ic"><i class="fa-solid fa-gamepad" aria-hidden="true"></i></div><b>OpenVibe.Games</b><span>Scraplandia and browser games</span><span class="go">openvibe.games →</span></a>
++ <a class="card" href="https://openvibe.media"><div class="ic"><i class="fa-solid fa-photo-film" aria-hidden="true"></i></div><b>OpenVibe.Media</b><span>VODs, clips and files</span><span class="go">openvibe.media →</span></a>
++ <a class="card" href="https://openvibe.network"><div class="ic"><i class="fa-solid fa-circle-nodes" aria-hidden="true"></i></div><b>OpenVibe.Network</b><span>One account, every site</span><span class="go">openvibe.network →</span></a>
++ </div>
++ <h2 style="margin-top:28px;font-size:16px">More rooms opening</h2>
++ <div class="rooms" style="margin-top:8px">
++ <a href="https://openvibe.chat/"><i class="fa-solid fa-comments" aria-hidden="true"></i>OpenVibe.Chat</a>
++ <a href="https://openvibe.codes/"><i class="fa-solid fa-code" aria-hidden="true"></i>OpenVibe.Codes</a>
++ <a href="https://openvibe.blog/"><i class="fa-solid fa-pen-nib" aria-hidden="true"></i>OpenVibe.Blog</a>
++ <a href="https://openvibe.news/"><i class="fa-solid fa-newspaper" aria-hidden="true"></i>OpenVibe.News</a>
++ <a href="https://openvibe.reviews/"><i class="fa-solid fa-star-half-stroke" aria-hidden="true"></i>OpenVibe.Reviews</a>
++ <a href="https://openvibe.tips/"><i class="fa-solid fa-hand-holding-heart" aria-hidden="true"></i>OpenVibe.Tips</a>
++ <a href="https://openvibe.vip/"><i class="fa-solid fa-crown" aria-hidden="true"></i>OpenVibe.VIP</a>
++ <a href="https://openvibe.trade/"><i class="fa-solid fa-chart-line" aria-hidden="true"></i>OpenVibe.Trade</a>
++ <a href="https://openvibe.host/"><i class="fa-solid fa-server" aria-hidden="true"></i>OpenVibe.Host</a>
++ <a href="https://openvibe.deals/"><i class="fa-solid fa-tags" aria-hidden="true"></i>OpenVibe.Deals</a>
++ <a href="https://openvibe.coupons/"><i class="fa-solid fa-ticket" aria-hidden="true"></i>OpenVibe.Coupons</a>
++ <a href="https://openre.stream/"><i class="fa-solid fa-satellite-dish" aria-hidden="true"></i>OpenRe.Stream</a>
++ </div>
++ </section>
++
++ <div class="strip">
++ <span class="ov-mark" data-size="44" data-variant="wiki"></span>
++ <h3>Open source. Community run.</h3>
++ <p>Every OpenVibe site is built in the open by the people using it — free speech within the rules, no gatekeeping, one identity that follows you everywhere.</p>
++ <a class="btn" href="https://github.com/OpenVibers" rel="noopener"><i class="fa-brands fa-github"></i> OpenVibers on GitHub</a>
++ </div>
++</main>
++<div id="ov-footer"></div>
++<script src="https://openvibe.network/shared/ov-mark.js" async></script>
++<script src="https://openvibe.network/shared/navbar.js"></script>
++<script src="https://openvibe.network/shared/footer.js"></script>
++<script>
++(function () {
++ if (window.OpenVibeNavbar) { try { OpenVibeNavbar.init({ service: 'wiki', apiBase: 'https://openvibe.network', links: [{ label: 'What it will be', href: '#what' }, { label: 'The network', href: 'https://openvibe.network/#network', external: false }], history: { type: 'page', title: 'OpenVibe.Wiki' } }); } catch (e) {} }
++ if (window.OpenVibeFooter) { try { OpenVibeFooter.init({ service: 'wiki', variant: 'full', links: [{ heading: 'OpenVibe.Wiki', items: [{ name: 'Sign in', url: 'https://openvibe.network/login?return=https%3A%2F%2Fopenvibe.wiki%2F' }, { name: 'The network', url: 'https://openvibe.network/#network' }, { name: 'Discord', url: 'https://discord.gg/M6MuRUaeJj' }] }] }); } catch (e) {} }
++})();
++</script>
++</body>
++</html>
ddiff --git a/dist/openvibe.wiki/manifest.webmanifest b/dist/openvibe.wiki/manifest.webmanifest
nnew file mode 100644
iindex 0000000..261ccc7
---- /dev/null
++++ b/dist/openvibe.wiki/manifest.webmanifest
@@@ -0,0 +1,20 @@
++{
++ "name": "OpenVibe.Wiki",
++ "short_name": "Wiki",
++ "start_url": "/",
++ "display": "standalone",
++ "background_color": "#0a0f1c",
++ "theme_color": "#34d399",
++ "icons": [
++ {
++ "src": "https://openvibe.network/assets/logo-192.png",
++ "sizes": "192x192",
++ "type": "image/png"
++ },
++ {
++ "src": "https://openvibe.network/assets/logo-512.png",
++ "sizes": "512x512",
++ "type": "image/png"
++ }
++ ]
++}
ddiff --git a/dist/openvibe.wiki/robots.txt b/dist/openvibe.wiki/robots.txt
nnew file mode 100644
iindex 0000000..fd4d850
---- /dev/null
++++ b/dist/openvibe.wiki/robots.txt
@@@ -0,0 +1,4 @@
++User-agent: *
++Allow: /
++Disallow: /auth/
++Sitemap: https://openvibe.wiki/sitemap.xml
ddiff --git a/dist/openvibe.wiki/sitemap.xml b/dist/openvibe.wiki/sitemap.xml
nnew file mode 100644
iindex 0000000..1272711
---- /dev/null
++++ b/dist/openvibe.wiki/sitemap.xml
@@@ -0,0 +1,4 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
++ <url><loc>https://openvibe.wiki/</loc><lastmod>2026-09-18</lastmod><changefreq>weekly</changefreq><priority>1.0</priority></url>
++</urlset>
ddiff --git a/sites.json b/sites.json
nnew file mode 100644
iindex 0000000..82076ed
---- /dev/null
++++ b/sites.json
@@@ -0,0 +1,218 @@
++{
++ "network": {
++ "core": "OpenVibe",
++ "networkUrl": "https://openvibe.network",
++ "discord": "https://discord.gg/M6MuRUaeJj",
++ "github": "https://github.com/OpenVibers",
++ "liveSites": [
++ { "id": "live", "name": "OpenVibe.Live", "url": "https://openvibe.live", "desc": "Go live, chat, clip, restream", "icon": "fa-tower-broadcast" },
++ { "id": "tools", "name": "OpenVibe.Tools", "url": "https://openvibe.tools", "desc": "Hundreds of online tools", "icon": "fa-screwdriver-wrench" },
++ { "id": "community", "name": "OpenVibe.Community", "url": "https://openvibe.community", "desc": "Pastes, posts, people", "icon": "fa-people-group" },
++ { "id": "games", "name": "OpenVibe.Games", "url": "https://openvibe.games", "desc": "Scraplandia and browser games", "icon": "fa-gamepad" },
++ { "id": "media", "name": "OpenVibe.Media", "url": "https://openvibe.media", "desc": "VODs, clips and files", "icon": "fa-photo-film" },
++ { "id": "network", "name": "OpenVibe.Network", "url": "https://openvibe.network", "desc": "One account, every site", "icon": "fa-circle-nodes" }
++ ]
++ },
++ "sites": [
++ {
++ "domain": "openvibe.chat", "tld": "chat", "name": "OpenVibe.Chat", "icon": "fa-comments", "accent": "#a78bfa",
++ "tagline": "One chat for the whole network.",
++ "description": "OpenVibe.Chat is the communication layer of the OpenVibe network: global rooms, stream chat, direct messages, group rooms, voice calls and text-to-speech — one identity, every conversation.",
++ "pillars": [
++ ["Global rooms", "Rooms that span every OpenVibe site, with the same moderation tools everywhere."],
++ ["Direct messages", "DMs and group rooms tied to your OpenVibe account, not to one website."],
++ ["Calls & voice", "Voice rooms and streamer-to-viewer calls, the same engine Live uses today."],
++ ["TTS & audio queues", "Text-to-speech, soundboards and audio queues for streams and rooms."]
++ ],
++ "meanwhile": [
++ ["Chat on OpenVibe.Live", "https://openvibe.live/chat", "The global chat is already live there — same account, same rules."],
++ ["Voice channels", "https://openvibe.live/chat", "Voice rooms run inside Live's chat today."]
++ ],
++ "keywords": "openvibe chat, community chat, voice rooms, direct messages, free speech chat"
++ },
++ {
++ "domain": "openvibe.codes", "tld": "codes", "name": "OpenVibe.Codes", "icon": "fa-code", "accent": "#22d3ee",
++ "tagline": "Build on OpenVibe.",
++ "description": "OpenVibe.Codes is the developer portal of the OpenVibe network: API and SDK documentation, the service and capability registry, event schemas, mod publishing, starter templates and vibe-coding sessions.",
++ "pillars": [
++ ["API & SDK docs", "One place for every OpenVibe API: identity, media, chat, live, community."],
++ ["Contracts & events", "Service manifests, capability schemas and the event backbone, documented."],
++ ["Mods & templates", "Publish mods and bots, start from templates, ship to the network."],
++ ["Vibe-coding", "Publish coding sessions and let people build alongside you."]
++ ],
++ "meanwhile": [
++ ["OpenVibe on GitHub", "https://github.com/OpenVibers", "Every OpenVibe service is open source. Read, fork, contribute."],
++ ["WHIP & streaming docs", "https://openvibe.live/documentation", "The streaming API and ingest docs live on OpenVibe.Live today."],
++ ["Dev tools", "https://dev.openvibe.tools", "Formatters, encoders and validators on OpenVibe.Tools."]
++ ],
++ "keywords": "openvibe api, openvibe sdk, developer portal, open source streaming api, mods"
++ },
++ {
++ "domain": "openvibe.blog", "tld": "blog", "name": "OpenVibe.Blog", "icon": "fa-pen-nib", "accent": "#f472b6",
++ "tagline": "Long-form, yours to keep.",
++ "description": "OpenVibe.Blog is the publishing home of the OpenVibe network: the official OpenVibe blog and blogs for every member — drafts, scheduled posts, media-rich writing, comments and feeds, with your OpenVibe account.",
++ "pillars": [
++ ["The OpenVibe blog", "Release notes, network updates and the story of the project."],
++ ["Your blog", "A blog for every account: drafts, tags, media, scheduling."],
++ ["Comments & feeds", "Discussion through OpenVibe.Community; RSS for everyone."],
++ ["Themes that follow you", "Your network theme is your blog theme, if you want it to be."]
++ ],
++ "meanwhile": [
++ ["Updates on OpenVibe.Live", "https://openvibe.live/updates", "What shipped, as it ships."],
++ ["Pastes", "https://openvibe.community/pastes", "Share text and code today on OpenVibe.Community."]
++ ],
++ "keywords": "openvibe blog, community blog, open source blogging"
++ },
++ {
++ "domain": "openvibe.wiki", "tld": "wiki", "name": "OpenVibe.Wiki", "icon": "fa-book", "accent": "#34d399",
++ "tagline": "Knowledge, with sources.",
++ "description": "OpenVibe.Wiki is the knowledge space of the OpenVibe network: wiki spaces you can build and edit together, source-backed and AI-assisted, with page trees, citations, media and discussion.",
++ "pillars": [
++ ["Spaces", "A wiki space per topic, game, community or project."],
++ ["Source-backed", "Every generated page carries its sources; every edit is yours."],
++ ["Page trees & history", "Organise, revise, roll back."],
++ ["Discussion", "Talk pages through OpenVibe.Community."]
++ ],
++ "meanwhile": [
++ ["OpenVibe documentation", "https://openvibe.live/documentation", "The streaming docs are the first wiki-like space of the network."]
++ ],
++ "keywords": "openvibe wiki, community wiki, knowledge base"
++ },
++ {
++ "domain": "openvibe.news", "tld": "news", "name": "OpenVibe.News", "icon": "fa-newspaper", "accent": "#fb923c",
++ "tagline": "Sourced. Summarised. Many angles.",
++ "description": "OpenVibe.News aggregates the news with transparency: sourced stories, summaries that show their sources, multiple angles side by side, topic pages and framing you control — not an algorithm you can't see.",
++ "pillars": [
++ ["Sources first", "Every summary links to what it was built from."],
++ ["Many angles", "Read the same story from several perspectives, side by side."],
++ ["Your framing", "You choose the lens; nothing is chosen for you silently."],
++ ["Topics", "Follow topics across sources, with your OpenVibe account."]
++ ],
++ "meanwhile": [
++ ["Network updates", "https://openvibe.live/updates", "What is happening across OpenVibe."]
++ ],
++ "keywords": "openvibe news, transparent news, news aggregation, multiple perspectives"
++ },
++ {
++ "domain": "openvibe.reviews", "tld": "reviews", "name": "OpenVibe.Reviews", "icon": "fa-star-half-stroke", "accent": "#facc15",
++ "tagline": "What people actually say.",
++ "description": "OpenVibe.Reviews gathers what people say about products, services, employers, hosts and communities across many sources — with provenance, without fake ratings — and lets the community discuss it.",
++ "pillars": [
++ ["Entity pages", "One page per product, service or place, built from many sources."],
++ ["Provenance", "Every quote links back to where it was said."],
++ ["No fake ratings", "Summaries, not invented stars."],
++ ["Discussion", "Community threads through OpenVibe.Community."]
++ ],
++ "meanwhile": [
++ ["Talk about it", "https://openvibe.community", "Community threads are the first stop."]
++ ],
++ "keywords": "openvibe reviews, review aggregation, honest reviews"
++ },
++ {
++ "domain": "openvibe.tips", "tld": "tips", "name": "OpenVibe.Tips", "icon": "fa-hand-holding-heart", "accent": "#4ade80",
++ "tagline": "Support the people you watch.",
++ "description": "OpenVibe.Tips is the tipping and alerts layer of the OpenVibe network: tips, donation goals, superchats, paid text-to-speech and media requests, with alert overlays for creators.",
++ "pillars": [
++ ["Tips & goals", "Tip a creator, fund a goal, see it land on stream."],
++ ["Superchat & TTS", "Paid messages read out on stream, through OpenVibe.Chat."],
++ ["Alert overlays", "Overlays for OBS and the browser, themed with the network."],
++ ["One ledger", "Every transaction on the network's own ledger, visible to you."]
++ ],
++ "meanwhile": [
++ ["Tip with Vibes on OpenVibe.Live", "https://openvibe.live", "Tips already work on Live today."]
++ ],
++ "keywords": "openvibe tips, tip streamers, donation alerts, superchat"
++ },
++ {
++ "domain": "openvibe.vip", "tld": "vip", "name": "OpenVibe.VIP", "icon": "fa-crown", "accent": "#e879f9",
++ "tagline": "Memberships, network-wide.",
++ "description": "OpenVibe.VIP is the membership layer of the OpenVibe network: creator memberships, channel subscriptions, VIP tiers and perks that unlock across Live, Community, Blog and more.",
++ "pillars": [
++ ["Creator memberships", "Subscribe to the people you watch; perks follow you everywhere."],
++ ["Network VIP", "One membership that supports the whole network."],
++ ["Perks", "Badges, emotes, early access, gated posts — set by creators."],
++ ["Transparent", "What it costs and where it goes, in the open."]
++ ],
++ "meanwhile": [
++ ["Subscriptions on OpenVibe.Live", "https://openvibe.live", "Channel subscriptions exist on Live today."]
++ ],
++ "keywords": "openvibe vip, creator memberships, subscriptions"
++ },
++ {
++ "domain": "openvibe.trade", "tld": "trade", "name": "OpenVibe.Trade", "icon": "fa-chart-line", "accent": "#60a5fa",
++ "tagline": "Watch, discuss, decide.",
++ "description": "OpenVibe.Trade is the market intelligence room of the OpenVibe network: watchlists, alerts, summaries and community discussion for markets, collectibles and deals — information and tools, never advice.",
++ "pillars": [
++ ["Watchlists & alerts", "Track what you care about, get told when it moves."],
++ ["Summaries", "What happened and why, with sources."],
++ ["Community", "Discuss with people, not bots."],
++ ["Not advice", "Tools and information only — always labelled as such."]
++ ],
++ "meanwhile": [
++ ["Deals", "https://openvibe.deals", "Deal discovery is the sibling room."]
++ ],
++ "keywords": "openvibe trade, watchlists, market alerts, community trading tools"
++ },
++ {
++ "domain": "openvibe.host", "tld": "host", "name": "OpenVibe.Host", "icon": "fa-server", "accent": "#94a3b8",
++ "tagline": "Run it yourself.",
++ "description": "OpenVibe.Host is the hosting and deployment surface of the OpenVibe network: deploy OpenVibe services, bots, mods and static sites, with TLS, DNS and logs handled for you.",
++ "pillars": [
++ ["Service hosting", "Every OpenVibe service, deployable in one step."],
++ ["Bots & mods", "Host your bot or mod next to the network it talks to."],
++ ["Static sites", "A folder in, a domain out, with TLS."],
++ ["Open source", "The same deploy tooling the network runs on."]
++ ],
++ "meanwhile": [
++ ["Deploy docs", "https://github.com/OpenVibers", "Every service ships its own deploy scripts on GitHub."]
++ ],
++ "keywords": "openvibe host, hosting, deployment, self-hosting openvibe"
++ },
++ {
++ "domain": "openvibe.deals", "tld": "deals", "name": "OpenVibe.Deals", "icon": "fa-tags", "accent": "#f97316",
++ "tagline": "Deals worth seeing.",
++ "description": "OpenVibe.Deals is community deal discovery for the OpenVibe network: deals people vote on, hotness that reflects real interest, keyword alerts, price comparisons and honest discussion.",
++ "pillars": [
++ ["Voted, not paid for", "Deals rise because people like them."],
++ ["Alerts", "Tell it what you want; it tells you when it is cheap."],
++ ["Compare", "Summaries and comparisons, with sources."],
++ ["Discuss", "Threads through OpenVibe.Community."]
++ ],
++ "meanwhile": [
++ ["Coupons", "https://openvibe.coupons", "The coupon room is the sibling of this one."]
++ ],
++ "keywords": "openvibe deals, community deals, deal alerts"
++ },
++ {
++ "domain": "openvibe.coupons", "tld": "coupons", "name": "OpenVibe.Coupons", "icon": "fa-ticket", "accent": "#fbbf24",
++ "tagline": "Codes that actually work.",
++ "description": "OpenVibe.Coupons is community-checked coupon discovery: codes matched to stores, validity reported by real people, expirations tracked, and a browser helper on the way.",
++ "pillars": [
++ ["Checked by people", "Codes that worked, codes that didn't, reported honestly."],
++ ["Store matching", "The right codes for the store you are on."],
++ ["Expiry tracking", "Dead codes go away."],
++ ["Browser helper", "Apply codes where you shop — coming with the site."]
++ ],
++ "meanwhile": [
++ ["Deals", "https://openvibe.deals", "Deal discovery is the sibling of this room."]
++ ],
++ "keywords": "openvibe coupons, coupon codes, community coupons"
++ },
++ {
++ "domain": "openre.stream", "core": "OpenRe", "tld": "stream", "name": "OpenRe.Stream", "icon": "fa-satellite-dish", "accent": "#ef4444",
++ "tagline": "Ingest and restream, in the open.",
++ "description": "OpenRe.Stream is the ingest and restream infrastructure behind OpenVibe.Live: RTMP, WHIP and SRT ingest, stream lifecycle, restream destinations and output status — the plumbing, documented and open.",
++ "pillars": [
++ ["Ingest", "RTMP, WHIP/WebRTC and SRT, with keys and lifecycle in one place."],
++ ["Restream", "Twitch, YouTube, Kick, SRT and RobotStreamer destinations."],
++ ["Status", "Live acknowledgement, errors relayed in plain words, uptime."],
++ ["Open", "Run it yourself; the code is on GitHub."]
++ ],
++ "meanwhile": [
++ ["Go live on OpenVibe.Live", "https://openvibe.live/broadcast", "Ingest and restreaming run inside Live today."],
++ ["Restreaming docs", "https://github.com/OpenVibers/OpenVibe.Live/blob/main/docs/restreaming.md", "How the restream paths work."]
++ ],
++ "keywords": "openre stream, rtmp ingest, whip, srt, restream, open source streaming infrastructure"
++ }
++ ]
++}