openvibers/openvibe.shared brand.js
brand.js
| 1 | ; |
| 2 | |
| 3 | // ═══════════════════════════════════════════════════════════════ |
| 4 | // OpenVibe — Brand Constants |
| 5 | // Shared across all OpenVibe services for consistent branding. |
| 6 | // Values are seeded with OpenVibe defaults and can be |
| 7 | // overridden at runtime via the URL registry / admin panel. |
| 8 | // ═══════════════════════════════════════════════════════════════ |
| 9 | |
| 10 | // ── Default (OpenVibe) values ──────────────────────────── |
| 11 | // These are the canonical defaults for the OpenVibe deployment. |
| 12 | // White-label installs override via the URL registry. |
| 13 | |
| 14 | const BRAND_DEFAULTS = Object.freeze({ |
| 15 | networkName: 'OpenVibe', |
| 16 | networkServiceName: 'OpenVibe.Network', |
| 17 | toolsServiceName: 'OpenVibe.Tools', |
| 18 | streamerServiceName:'OpenVibe.Live', |
| 19 | gamesServiceName: 'OpenVibe.Games', |
| 20 | mediaServiceName: 'OpenVibe.Media', |
| 21 | tagline: 'One Account. All of OpenVibe.', |
| 22 | campTagline: 'Open Live Streaming, Community Run', |
| 23 | toolsSubdomainBase: 'openvibe.tools', |
| 24 | discord: 'https://discord.gg/M6MuRUaeJj', |
| 25 | github: 'https://github.com/OpenVibe.Live', |
| 26 | }); |
| 27 | |
| 28 | function getDefaultBrandUrls(env = process.env) { |
| 29 | return { |
| 30 | network: env.OV_NETWORK_URL || 'https://openvibe.network', |
| 31 | login: env.LOGIN_URL || env.OV_NETWORK_LOGIN_URL || env.OV_NETWORK_URL || 'https://openvibe.network', |
| 32 | tools: env.OV_TOOLS_URL || 'https://openvibe.tools', |
| 33 | live: env.OV_LIVE_URL || 'https://openvibe.live', |
| 34 | games: env.OV_GAMES_URL || 'https://openvibe.games', |
| 35 | media: env.OV_MEDIA_URL || 'https://openvibe.media', |
| 36 | community:env.OV_COMMUNITY_URL || 'https://openvibe.community', |
| 37 | // Tool satellites (Host-routed under openvibe.tools) |
| 38 | maps: env.OV_MAPS_URL || 'https://maps.openvibe.tools', |
| 39 | food: env.OV_FOOD_URL || 'https://food.openvibe.tools', |
| 40 | img: env.OV_IMG_URL || 'https://img.openvibe.tools', |
| 41 | yt: env.OV_YT_URL || 'https://yt.openvibe.tools', |
| 42 | audio: env.OV_AUDIO_URL || 'https://audio.openvibe.tools', |
| 43 | text: env.OV_TEXT_URL || 'https://text.openvibe.tools', |
| 44 | logo: env.OV_LOGO_URL || 'https://logo.openvibe.tools', |
| 45 | docs: env.OV_DOCS_URL || 'https://docs.openvibe.tools', |
| 46 | net: env.OV_NET_URL || 'https://net.openvibe.tools', |
| 47 | dev: env.OV_DEV_URL || 'https://dev.openvibe.tools', |
| 48 | pastes: env.OV_PASTES_URL || 'https://pastes.openvibe.tools', |
| 49 | // Legacy aliases (older callers) — same targets as above |
| 50 | streamer: env.OV_LIVE_URL || 'https://openvibe.live', |
| 51 | quest: env.OV_GAMES_URL || 'https://openvibe.games', |
| 52 | discord: BRAND_DEFAULTS.discord, |
| 53 | github: BRAND_DEFAULTS.github, |
| 54 | }; |
| 55 | } |
| 56 | |
| 57 | const DEFAULT_URLS = Object.freeze(getDefaultBrandUrls()); |
| 58 | |
| 59 | function resolveBrandUrls(overrides = {}, env = process.env) { |
| 60 | return Object.freeze({ |
| 61 | ...getDefaultBrandUrls(env), |
| 62 | ...overrides, |
| 63 | }); |
| 64 | } |
| 65 | |
| 66 | /** |
| 67 | * Build a brand object from a resolved URL registry map. |
| 68 | * Call this server-side when the canonical registry has been loaded. |
| 69 | * |
| 70 | * @param {Object} registry - resolved registry map from resolveRegistryValues() |
| 71 | * @param {Object} [env] - process.env fallback |
| 72 | * @returns {Object} brand object with names, urls, colors, services, oauth |
| 73 | */ |
| 74 | function buildBrandFromRegistry(registry = {}, env = process.env) { |
| 75 | const get = (key) => (registry[key]?.value) || null; |
| 76 | |
| 77 | const networkName = get('NETWORK_NAME') || BRAND_DEFAULTS.networkName; |
| 78 | const toolsServiceName = get('TOOLS_SERVICE_NAME') || BRAND_DEFAULTS.toolsServiceName; |
| 79 | const streamerServiceName= get('STREAMER_SERVICE_NAME')|| BRAND_DEFAULTS.streamerServiceName; |
| 80 | const gamesServiceName = get('GAMES_SERVICE_NAME') || BRAND_DEFAULTS.gamesServiceName; |
| 81 | const mediaServiceName = get('MEDIA_SERVICE_NAME') || BRAND_DEFAULTS.mediaServiceName; |
| 82 | const defaults = getDefaultBrandUrls(env); |
| 83 | const networkUrl = get('OV_NETWORK_URL') || defaults.network; |
| 84 | const liveUrl = get('OV_LIVE_URL') || defaults.live; |
| 85 | const toolsUrl = get('OV_TOOLS_URL') || defaults.tools; |
| 86 | const gamesUrl = get('OV_GAMES_URL') || defaults.games; |
| 87 | const mediaUrl = get('OV_MEDIA_URL') || defaults.media; |
| 88 | |
| 89 | const urls = resolveBrandUrls({ |
| 90 | network: networkUrl, |
| 91 | login: get('OV_NETWORK_LOGIN_URL') || networkUrl, |
| 92 | live: liveUrl, |
| 93 | streamer: liveUrl, |
| 94 | tools: toolsUrl, |
| 95 | games: gamesUrl, |
| 96 | quest: gamesUrl, |
| 97 | media: mediaUrl, |
| 98 | }, env); |
| 99 | |
| 100 | // Build service list using registry URLs where available |
| 101 | const services = [ |
| 102 | { id: 'live', name: streamerServiceName, url: liveUrl, description: 'Open live streaming, community run' }, |
| 103 | { id: 'tools', name: toolsServiceName, url: toolsUrl, description: 'Online tools for everyone' }, |
| 104 | { id: 'games', name: gamesServiceName, url: gamesUrl, description: 'Games & Community Canvas' }, |
| 105 | { id: 'media', name: mediaServiceName, url: mediaUrl, description: 'VODs, Clips, Pastes & Files' }, |
| 106 | { id: 'network', name: BRAND_DEFAULTS.networkServiceName, url: networkUrl, description: 'Accounts, SSO & OpenCoins' }, |
| 107 | ]; |
| 108 | |
| 109 | return Object.freeze({ |
| 110 | name: networkName, |
| 111 | toolsName: toolsServiceName, |
| 112 | streamerName:streamerServiceName, |
| 113 | gamesName: gamesServiceName, |
| 114 | mediaName: mediaServiceName, |
| 115 | tagline: BRAND_DEFAULTS.tagline, |
| 116 | campTagline: BRAND_DEFAULTS.campTagline, |
| 117 | toolsSubdomainBase: get('TOOLS_SUBDOMAIN_BASE') || BRAND_DEFAULTS.toolsSubdomainBase, |
| 118 | urls: Object.freeze(urls), |
| 119 | colors: BRAND.colors, |
| 120 | oauth: BRAND.oauth, |
| 121 | services: Object.freeze(services), |
| 122 | }); |
| 123 | } |
| 124 | |
| 125 | const BRAND = Object.freeze({ |
| 126 | name: BRAND_DEFAULTS.networkName, |
| 127 | tagline: BRAND_DEFAULTS.tagline, |
| 128 | campTagline: BRAND_DEFAULTS.campTagline, |
| 129 | |
| 130 | urls: resolveBrandUrls(), |
| 131 | |
| 132 | // Palette per CONTRACTS.md |
| 133 | colors: Object.freeze({ |
| 134 | accent: '#8b5cf6', |
| 135 | accentLight: '#a78bfa', |
| 136 | accentDark: '#6d28d9', |
| 137 | secondary: '#22d3ee', |
| 138 | bgDark: '#131318', |
| 139 | flame: '#a78bfa', // legacy alias for accentLight |
| 140 | signalRed: '#e74c3c', |
| 141 | success: '#2ecc71', |
| 142 | warning: '#f39c12', |
| 143 | danger: '#e74c3c', |
| 144 | info: '#3498db', |
| 145 | }), |
| 146 | |
| 147 | // OAuth2 client IDs for each service (seeded in the Network DB) |
| 148 | oauth: Object.freeze({ |
| 149 | live: 'live', |
| 150 | tools: 'tools', |
| 151 | games: 'games', |
| 152 | media: 'media', |
| 153 | }), |
| 154 | |
| 155 | // Primary services in the network (for dashboard display, health checks, etc.) |
| 156 | // Static list with OpenVibe defaults — use buildBrandFromRegistry() for live values. |
| 157 | services: Object.freeze([ |
| 158 | { id: 'live', name: 'OpenVibe.Live', url: 'https://openvibe.live', description: 'Open live streaming, community run' }, |
| 159 | { id: 'tools', name: 'OpenVibe.Tools', url: 'https://openvibe.tools', description: 'Online tools for everyone' }, |
| 160 | { id: 'games', name: 'OpenVibe.Games', url: 'https://openvibe.games', description: 'Games & Community Canvas' }, |
| 161 | { id: 'media', name: 'OpenVibe.Media', url: 'https://openvibe.media', description: 'VODs, Clips, Pastes & Files' }, |
| 162 | { id: 'network', name: 'OpenVibe.Network', url: 'https://openvibe.network', description: 'Accounts, SSO & OpenCoins' }, |
| 163 | ]), |
| 164 | |
| 165 | // Tool sub-brands hosted by OpenVibe.Tools (<Name>.OpenVibe naming) |
| 166 | toolBrands: Object.freeze([ |
| 167 | { id: 'net', name: 'Net.OpenVibe', url: 'https://net.openvibe.tools', description: 'Network & Internet Diagnostics' }, |
| 168 | { id: 'dev', name: 'Dev.OpenVibe', url: 'https://dev.openvibe.tools', description: 'Developer & SEO Tools' }, |
| 169 | { id: 'paste', name: 'Paste.OpenVibe', url: 'https://pastes.openvibe.tools',description: 'Code & Text Sharing' }, |
| 170 | { id: 'maps', name: 'Maps.OpenVibe', url: 'https://maps.openvibe.tools', description: 'Camp & Shelter Locator' }, |
| 171 | { id: 'food', name: 'Food.OpenVibe', url: 'https://food.openvibe.tools', description: 'Food Resource Finder' }, |
| 172 | { id: 'img', name: 'Img.OpenVibe', url: 'https://img.openvibe.tools', description: 'Image Converter & Tools' }, |
| 173 | { id: 'yt', name: 'YT.OpenVibe', url: 'https://yt.openvibe.tools', description: 'YouTube Downloader' }, |
| 174 | { id: 'audio', name: 'Audio.OpenVibe', url: 'https://audio.openvibe.tools', description: 'Audio Converter & Effects' }, |
| 175 | { id: 'text', name: 'Text.OpenVibe', url: 'https://text.openvibe.tools', description: 'Text Generation & Unicode' }, |
| 176 | { id: 'logo', name: 'Logo.OpenVibe', url: 'https://logo.openvibe.tools', description: 'Logo & Title Card Maker' }, |
| 177 | { id: 'docs', name: 'Docs.OpenVibe', url: 'https://docs.openvibe.tools', description: 'PDF & Document Tools' }, |
| 178 | ]), |
| 179 | }); |
| 180 | |
| 181 | module.exports = { BRAND, BRAND_DEFAULTS, resolveBrandUrls, buildBrandFromRegistry }; |
| 182 |