Files
html/technology-radar.html
opus c42b0ec0fb
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
auto-sync via WEVIA git_sync_all intent 2026-04-21T12:08:27+02:00
2026-04-21 12:08:27 +02:00

684 lines
67 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png type="image/x-icon">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WEVAL Technology Radar</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,300;9..40,400;9..40,500;9..40,600;9..40,700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
*{box-sizing:border-box;margin:0;padding:0}
:root{--bg:#ffffff;--card:#f8fafc;--border:#e2e8f0;--text:#1e293b;--dim:#64748b;--muted:#94a3b8;--dark:#cbd5e1;--green:#059669;--blue:#3B82F6;--yellow:#F59E0B;--purple:#A855F7}
html{scroll-behavior:smooth}
body{background:var(--bg);color:var(--text);font-family:'DM Sans','Segoe UI',sans-serif;min-height:100vh;-webkit-font-smoothing:antialiased}
::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:var(--bg)}::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px}
.mono{font-family:'JetBrains Mono',monospace}
/* Animations */
@keyframes fadeUp{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}@keyframes wevalPulse{0%,100%{r:5.5;opacity:.85}50%{r:7.5;opacity:1}}.blip-dot.weval-dot{animation:wevalPulse 2.5s ease-in-out infinite}
@keyframes shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}
@keyframes radarSweep{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}
.fade-up{animation:fadeUp .5s ease-out forwards;opacity:0}
/* Layout */
.wrap{max-width:1200px;margin:0 auto;padding:40px 24px 0}
.glow-line{height:1px;background:linear-gradient(90deg,transparent,var(--green),var(--blue),transparent);animation:shimmer 3s linear infinite;background-size:200% 100%;margin-bottom:36px}
/* Radar Section */
.radar-section{display:flex;gap:40px;align-items:center;flex-wrap:wrap;margin-bottom:48px}
.radar-svg-wrap{flex:1 1 520px;min-width:300px;position:relative}
.radar-legend{flex:1 1 260px;min-width:240px}
.radar-svg{width:100%;max-width:560px;display:block;margin:0 auto}
.radar-sweep{transform-origin:280px 280px;animation:radarSweep 8s linear infinite;opacity:.08}
/* Blips */
.blip{cursor:pointer;transition:all .15s}
.blip:hover .blip-dot{r:8;opacity:1}
.blip:hover .blip-glow{opacity:.15}
.blip-label{pointer-events:none;opacity:0;transition:opacity .15s}
.blip:hover .blip-label{opacity:1}
/* Legend */
.legend-section{margin-bottom:28px}
.legend-title{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:1.5px;margin-bottom:12px}
.legend-row{display:flex;align-items:center;gap:10px;margin-bottom:10px;cursor:pointer;transition:opacity .2s}
.legend-row:hover{opacity:.8}
.legend-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.legend-label{font-size:13px;color:#C8CAD4}
.legend-count{font-size:11px;color:var(--dark);margin-left:auto}
.ring-dot{width:10px;height:10px;border-radius:50%;border:2px solid;background:transparent;transition:background .2s}
.ring-dot.active{background:currentColor}
/* Stats box */
.stats-box{background:var(--card);border:1px solid var(--border);border-radius:10px;padding:16px}
.stats-row{display:flex;justify-content:space-between;margin-bottom:8px}
.stats-row:last-child{margin-bottom:0}
.stats-label{font-size:12px;color:var(--dim)}
.stats-val{font-size:16px;font-weight:700}
/* Language bar */
.lang-section{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:16px 20px;margin-bottom:28px}
.lang-bar{display:flex;gap:3px;height:8px;border-radius:4px;overflow:hidden;margin-bottom:10px}
.lang-segment{border-radius:2px;transition:flex .8s}
.lang-labels{display:flex;flex-wrap:wrap;gap:8px 20px}
.lang-item{display:flex;align-items:center;gap:6px;font-size:12px}
.lang-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
/* Filters */
.filter-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-bottom:24px}
.search-wrap{position:relative}
.search-icon{position:absolute;left:12px;top:50%;transform:translateY(-50%);opacity:.4}
.search-input{background:var(--card);border:1px solid var(--border);border-radius:8px;padding:10px 14px 10px 36px;color:var(--text);font-size:14px;font-family:inherit;width:320px;max-width:100%;outline:none;transition:border-color .2s}
.search-input:focus{border-color:var(--blue)}
.search-input::placeholder{color:var(--muted)}
.cat-btns{display:flex;gap:6px;flex-wrap:wrap;flex:1}
.cat-btn{padding:8px 16px;border-radius:8px;border:1px solid var(--border);background:transparent;color:#8B8FA3;cursor:pointer;font-size:13px;font-family:inherit;transition:all .2s;white-space:nowrap}
.cat-btn:hover{border-color:var(--blue);color:var(--text)}
.cat-btn.active{background:#1A1F35;border-color:var(--blue);color:#fff}
.result-count{font-size:13px;color:var(--muted);margin-bottom:16px}
/* Cards Grid */
.cards-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:14px;padding-bottom:60px}
.tool-card{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:20px;cursor:pointer;transition:all .25s;position:relative;overflow:hidden}
.tool-card:hover{border-color:#2A3050;transform:translateY(-2px);box-shadow:0 8px 32px rgba(0,0,0,.4)}
.tool-card::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,var(--sc),transparent);opacity:0;transition:opacity .25s}
.tool-card:hover::before{opacity:1}
.tool-card.weval-card{border-color:#14B8A6 !important}.tool-card.weval-card .card-name::after{content:" WEVAL";font-size:10px;color:#14B8A6;font-weight:500;margin-left:6px}
.tool-card.selected{box-shadow:0 0 20px color-mix(in srgb,var(--sc) 20%,transparent)}
.card-top{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:10px}
.card-name{font-size:17px;font-weight:600;color:#fff}
.card-logo{width:28px;height:28px;border-radius:6px;object-fit:contain;flex-shrink:0;background:rgba(255,255,255,.06);padding:2px}
.status-pill{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:20px;font-size:11px;font-weight:500;letter-spacing:.3px;text-transform:uppercase}
.status-dot{width:5px;height:5px;border-radius:50%}
.status-dot.pulse{animation:pulse 2s infinite}
.replaces-badge{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:4px;font-size:11px;background:rgba(245,158,11,.08);color:var(--yellow);border:1px solid rgba(245,158,11,.15)}
.card-stars{text-align:right;flex-shrink:0}
.card-stars-num{font-size:18px;font-weight:700;color:var(--yellow);line-height:1}
.card-stars-label{font-size:10px;color:var(--muted);margin-top:2px}
.card-desc{font-size:13px;color:#8B8FA3;line-height:1.5;margin-bottom:12px}
.card-footer{display:flex;justify-content:space-between;align-items:center}
.card-lang{display:inline-flex;align-items:center;gap:4px;font-size:11px;color:var(--dim)}
.card-license{font-size:11px;color:var(--dark)}
.card-arrow{opacity:.2;transition:opacity .2s}
.tool-card:hover .card-arrow{opacity:.6}
/* Header */
.header{display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:16px;margin-bottom:12px}
.logo-row{display:flex;align-items:center;gap:12px;margin-bottom:8px}
.logo{width:36px;height:36px;border-radius:8px;background:linear-gradient(135deg,var(--green),var(--blue));display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:700;color:var(--bg)}
.subtitle{color:var(--dim);font-size:15px;margin-top:8px;max-width:520px;line-height:1.5}
.lang-toggle{background:var(--card);border:1px solid var(--border);border-radius:6px;padding:4px 10px;color:#8B8FA3;font-size:12px;cursor:pointer;transition:all .2s}
.lang-toggle:hover{border-color:var(--blue);color:#fff}
h1{font-size:36px;font-weight:700;line-height:1.1;background:linear-gradient(135deg,#E8E9ED 40%,#8B8FA3);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
/* Footer */
.footer{text-align:center;padding:32px 0 48px;border-top:1px solid var(--border);margin-top:20px}
@media(max-width:768px){
.radar-section{flex-direction:column}
.search-input{width:100%}
.cards-grid{grid-template-columns:1fr}
}
</style>
</head>
<body>
<div class="wrap" id="app">
<!-- Header -->
<div class="header fade-up" style="animation-delay:.1s">
<div>
<div class="logo-row">
<div class="logo">W</div>
<span class="mono" style="font-size:12px;color:var(--muted);letter-spacing:2px;text-transform:uppercase">Technology Radar</span>
</div>
<h1 id="title">Our Open Source Arsenal</h1>
<p class="subtitle" id="subtitle">The sovereign tools we deploy, recommend, and explore for our clients.</p>
</div>
<button class="lang-toggle mono" id="langBtn" onclick="toggleLang()">FR</button>
</div>
<div class="glow-line"></div>
<!-- ═══ RADAR + LEGEND ═══ -->
<div class="radar-section fade-up" style="animation-delay:.2s">
<div class="radar-svg-wrap">
<svg id="radarSvg" class="radar-svg" viewBox="0 0 560 560" xmlns="http://www.w3.org/2000/svg"></svg>
</div>
<div class="radar-legend" id="radarLegend"></div>
</div>
<!-- Language bar -->
<div class="lang-section fade-up" style="animation-delay:.3s">
<div class="mono" style="font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:1;margin-bottom:12px" id="langTitle">Primary Languages</div>
<div class="lang-bar" id="langBar"></div>
<div class="lang-labels" id="langLabels"></div>
</div>
<!-- Filters -->
<div class="filter-row fade-up" style="animation-delay:.4s">
<div class="search-wrap">
<svg class="search-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
<input class="search-input" id="searchInput" placeholder="Search tool or product..." oninput="render()">
</div>
<div class="cat-btns" id="catBtns"></div>
</div>
<div class="result-count mono" id="resultCount"></div>
<!-- Cards -->
<div class="cards-grid" id="cardsGrid"></div>
<!-- Footer -->
<div class="footer">
<div class="mono" style="font-size:12px;color:var(--dark)" id="footerText">WEVAL Consulting · Casablanca · Digital Sovereignty · 2026</div>
</div>
</div>
<script>
const QC = ["#84CC16","#F97316","#A855F7","#EF4444"];
const QUADRANTS = [
{id:"ai",label:"Sovereign AI",labelFr:"IA Souveraine"},
{id:"infra",label:"DevOps & Infra",labelFr:"DevOps & Infra"},
{id:"business",label:"Business & Data",labelFr:"Business & Data"},
{id:"tic",label:"Marketing & Security",labelFr:"Digital & Sécurité"}
];
const STATUSES = {
use:{label:"We Use",labelFr:"On utilise",color:"#00E5A0",ring:0},
recommend:{label:"We Recommend",labelFr:"On recommande",color:"#3B82F6",ring:1},
explore:{label:"Exploring",labelFr:"On explore",color:"#F59E0B",ring:2}
};
const CATEGORIES = [
{id:"all",label:"All",labelFr:"Tout",icon:"◈"},
{id:"ai",label:"Sovereign AI",labelFr:"IA Souveraine",icon:"🧠"},
{id:"email",label:"Marketing & Automation",labelFr:"Marketing & Automation",icon:"✉"},
{id:"devops",label:"DevOps & Infra",labelFr:"DevOps & Infra",icon:"⚙"},
{id:"business",label:"Business Apps",labelFr:"Apps Business",icon:"📊"},
{id:"security",label:"Security",labelFr:"Sécurité",icon:"🛡"},
{id:"data",label:"Data & Analytics",labelFr:"Data & Analytics",icon:"📈"}
];
const LC = {TypeScript:"#3178C6",Go:"#00ADD8",Python:"#3776AB",JavaScript:"#F7DF1E",PHP:"#777BB4",Rust:"#DEA584","C++":"#F34B7D",Ruby:"#CC342D",Clojure:"#63B132",Elixir:"#6E4A7E"};
const TOOLS = [
{name:"Ollama",cat:"ai",quad:"ai",status:"use",stars:120000,lang:"Go",license:"MIT",replaces:"OpenAI API",desc:"Local LLM inference — 51 models on GPU",descFr:"Inférence LLM locale — 51 modèles sur GPU",url:"https://github.com/ollama/ollama",seed:.2},
{name:"Open WebUI",cat:"ai",quad:"ai",status:"use",stars:126000,lang:"TypeScript",license:"MIT",replaces:"ChatGPT Enterprise",desc:"Self-hosted chat with RAG, RBAC, SSO",descFr:"Chat self-hosted avec RAG, RBAC, SSO",url:"https://github.com/open-webui/open-webui",seed:.7},
{name:"Dify",cat:"ai",quad:"ai",status:"explore",stars:131000,lang:"TypeScript",license:"Apache-2.0",replaces:"LangChain Cloud",desc:"Visual AI workflow builder + agents",descFr:"Builder workflows IA visuel + agents",url:"https://github.com/langgenius/dify",seed:.3},
{name:"SearXNG",cat:"ai",quad:"ai",status:"use",stars:16000,lang:"Python",license:"AGPL-3.0",replaces:"Google Custom Search",desc:"Privacy-first metasearch — 229+ sources",descFr:"Métamoteur privé — 229+ sources",url:"https://github.com/searxng/searxng",seed:.5},
{name:"Qdrant",cat:"ai",quad:"ai",status:"explore",stars:23000,lang:"Rust",license:"Apache-2.0",replaces:"Pinecone",desc:"Vector DB for RAG with hybrid search",descFr:"Base vectorielle RAG + recherche hybride",url:"https://github.com/qdrant/qdrant",seed:.6},
{name:"Langflow",cat:"ai",quad:"ai",status:"explore",stars:145000,lang:"Python",license:"MIT",replaces:"Flowise Cloud",desc:"Visual multi-agent AI framework",descFr:"Framework IA multi-agents visuel",url:"https://github.com/langflow-ai/langflow",seed:.8},
{name:"vLLM",cat:"ai",quad:"ai",status:"use",stars:42000,lang:"Python",license:"Apache-2.0",replaces:"TGI / Triton",desc:"High-throughput LLM serving",descFr:"Serving LLM haut débit",url:"https://github.com/vllm-project/vllm",seed:.35},
{name:"ComfyUI",cat:"ai",quad:"ai",status:"explore",stars:105000,lang:"Python",license:"GPL-3.0",replaces:"Midjourney / DALL-E",desc:"Node-based Stable Diffusion engine",descFr:"Moteur Stable Diffusion par nœuds",url:"https://github.com/comfyanonymous/ComfyUI",seed:.15},
{name:"Mautic",cat:"email",quad:"tic",status:"recommend",stars:9300,lang:"PHP",license:"GPL-3.0",replaces:"HubSpot / Marketo",desc:"Marketing automation — campaigns, scoring",descFr:"Automatisation marketing — campagnes, scoring",url:"https://github.com/mautic/mautic",seed:.4},
{name:"Postal",cat:"email",quad:"tic",status:"recommend",stars:15000,lang:"Ruby",license:"MIT",replaces:"SendGrid / Mailgun",desc:"Self-hosted mail delivery + tracking",descFr:"Livraison email self-hosted + tracking",url:"https://github.com/postalserver/postal",seed:.65},
{name:"Listmonk",cat:"email",quad:"tic",status:"recommend",stars:15000,lang:"Go",license:"AGPL-3.0",replaces:"Mailchimp",desc:"High-perf newsletter — millions on 512MB",descFr:"Newsletter haute perf — millions sur 512MB",url:"https://github.com/knadh/listmonk",seed:.2},
{name:"n8n",cat:"devops",quad:"infra",status:"recommend",stars:178000,lang:"TypeScript",license:"Sustainable Use",replaces:"Zapier / Make",desc:"Workflow automation — 400+ integrations",descFr:"Automatisation — 400+ intégrations",url:"https://github.com/n8n-io/n8n",seed:.3},
{name:"Uptime Kuma",cat:"devops",quad:"infra",status:"use",stars:84000,lang:"JavaScript",license:"MIT",replaces:"Pingdom / UptimeRobot",desc:"Monitoring — 90+ notification channels",descFr:"Monitoring — 90+ canaux de notification",url:"https://github.com/louislam/uptime-kuma",seed:.6},
{name:"Grafana",cat:"devops",quad:"infra",status:"recommend",stars:73000,lang:"TypeScript",license:"AGPL-3.0",replaces:"Datadog Dashboards",desc:"Observability — metrics, logs, traces",descFr:"Observabilité — métriques, logs, traces",url:"https://github.com/grafana/grafana",seed:.75},
{name:"Coolify",cat:"devops",quad:"infra",status:"explore",stars:40000,lang:"PHP",license:"Apache-2.0",replaces:"Heroku / Vercel",desc:"Self-hosted PaaS — git push deploy",descFr:"PaaS self-hosted — déploiement git push",url:"https://github.com/coollabsio/coolify",seed:.15},
{name:"Gitea",cat:"devops",quad:"infra",status:"recommend",stars:48000,lang:"Go",license:"MIT",replaces:"GitHub / GitLab",desc:"Lightweight self-hosted Git + CI/CD",descFr:"Git self-hosted léger + CI/CD",url:"https://github.com/go-gitea/gitea",seed:.45},
{name:"Traefik",cat:"devops",quad:"infra",status:"use",stars:53000,lang:"Go",license:"MIT",replaces:"NGINX Plus / AWS ALB",desc:"Cloud-native reverse proxy + auto SSL",descFr:"Reverse proxy cloud-native + SSL auto",url:"https://github.com/traefik/traefik",seed:.85},
{name:"frp",cat:"devops",quad:"infra",status:"explore",stars:105000,lang:"Go",license:"Apache-2.0",replaces:"ngrok / Cloudflare Tunnels",desc:"Fast reverse proxy for local servers",descFr:"Reverse proxy rapide pour serveurs locaux",url:"https://github.com/fatedier/frp",seed:.55},
{name:"ERPNext",cat:"business",quad:"business",status:"recommend",stars:32000,lang:"Python",license:"GPL-3.0",replaces:"SAP Business One",desc:"Full ERP — accounting, HR, CRM",descFr:"ERP complet — comptabilité, RH, CRM",url:"https://github.com/frappe/erpnext",seed:.3},
{name:"Twenty CRM",cat:"business",quad:"business",status:"explore",stars:28000,lang:"TypeScript",license:"AGPL-3.0",replaces:"Salesforce / HubSpot",desc:"Modern CRM — Notion-like UX + GraphQL",descFr:"CRM moderne — UX Notion + GraphQL",url:"https://github.com/twentyhq/twenty",seed:.6},
{name:"Plane",cat:"business",quad:"business",status:"explore",stars:38600,lang:"TypeScript",license:"AGPL-3.0",replaces:"Jira / Linear",desc:"Project mgmt — sprints, modules, AI",descFr:"Gestion projet — sprints, modules, IA",url:"https://github.com/makeplane/plane",seed:.15},
{name:"Outline",cat:"business",quad:"business",status:"recommend",stars:30000,lang:"TypeScript",license:"BSL-1.1",replaces:"Notion / Confluence",desc:"Collaborative wiki + real-time + SSO",descFr:"Wiki collaboratif + temps réel + SSO",url:"https://github.com/outline/outline",seed:.75},
{name:"Supabase",cat:"business",quad:"business",status:"recommend",stars:98700,lang:"TypeScript",license:"Apache-2.0",replaces:"Firebase",desc:"Open Firebase — Postgres, Auth, Realtime",descFr:"Firebase open — Postgres, Auth, Realtime",url:"https://github.com/supabase/supabase",seed:.45},
{name:"Wazuh",cat:"security",quad:"tic",status:"recommend",stars:12000,lang:"C++",license:"GPL-2.0",replaces:"Splunk / CrowdStrike",desc:"SIEM/XDR — FIM, vuln detection, compliance",descFr:"SIEM/XDR — FIM, détection vulns, conformité",url:"https://github.com/wazuh/wazuh",seed:.8},
{name:"CrowdSec",cat:"security",quad:"tic",status:"explore",stars:9000,lang:"Go",license:"MIT",replaces:"Fail2ban (next-gen)",desc:"Crowd threat intel — 60× faster",descFr:"Threat intel collaborative — 60× plus rapide",url:"https://github.com/crowdsecurity/crowdsec",seed:.5},
{name:"Authentik",cat:"security",quad:"tic",status:"recommend",stars:15000,lang:"Python",license:"Custom",replaces:"Auth0 / Okta",desc:"Identity provider — SSO, MFA, LDAP, SCIM",descFr:"IdP — SSO, MFA, LDAP, SCIM",url:"https://github.com/goauthentik/authentik",seed:.1},
{name:"Metabase",cat:"data",quad:"business",status:"recommend",stars:40000,lang:"Clojure",license:"AGPL-3.0",replaces:"Tableau / Power BI",desc:"BI dashboards + natural language queries",descFr:"Dashboards BI + requêtes langage naturel",url:"https://github.com/metabase/metabase",seed:.9},
{name:"Superset",cat:"data",quad:"business",status:"explore",stars:65000,lang:"Python",license:"Apache-2.0",replaces:"Looker / Tableau",desc:"Enterprise BI — 40+ charts, SQL Lab",descFr:"BI entreprise — 40+ graphes, SQL Lab",url:"https://github.com/apache/superset",seed:.5},
{name:"PostHog",cat:"data",quad:"business",status:"explore",stars:31000,lang:"TypeScript",license:"MIT",replaces:"Mixpanel / Amplitude",desc:"Product analytics + session replay + A/B",descFr:"Analytics produit + session replay + A/B",url:"https://github.com/PostHog/posthog",seed:.2},
{name:"Plausible",cat:"data",quad:"business",status:"recommend",stars:22000,lang:"Elixir",license:"AGPL-3.0",replaces:"Google Analytics",desc:"Privacy analytics — <1KB, no cookies",descFr:"Analytics privé — <1KB, zero cookies",url:"https://github.com/plausible/analytics",seed:.65}
];
// WEVAL SaaS (62 products)
[{name:"WEVADS",cat:"weval",quad:"tic",status:"use",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/wevads.html",seed:0.16,isWeval:true},
{name:"Wevads IA",cat:"weval",quad:"ai",status:"use",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/wevads-ia.html",seed:0.75,isWeval:true},
{name:"DeliverAds",cat:"weval",quad:"tic",status:"use",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/deliverads.html",seed:0.85,isWeval:true},
{name:"Wevanalytics",cat:"weval",quad:"business",status:"use",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/arsenal.html",seed:0.25,isWeval:true},
{name:"Digital Platform",cat:"weval",quad:"tic",status:"use",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/email-platform.html",seed:0.9,isWeval:true},
{name:"WEVIA Enterprise",cat:"weval",quad:"ai",status:"use",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/wevia-enterprise.html",seed:0.21,isWeval:true},
{name:"Sentinel",cat:"weval",quad:"tic",status:"use",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/sentinel.html",seed:0.85,isWeval:true},
{name:"Consulting",cat:"weval",quad:"business",status:"use",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/consulting.html",seed:0.3,isWeval:true},
{name:"Wevia Inference",cat:"weval",quad:"ai",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/gpu-inference.html",seed:0.88,isWeval:true},
{name:"Content Factory",cat:"weval",quad:"ai",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/content-factory.html",seed:0.19,isWeval:true},
{name:"IA Arabe FR",cat:"weval",quad:"ai",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/ia-arabe.html",seed:0.32,isWeval:true},
{name:"WEVIA Agency",cat:"weval",quad:"ai",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/wevia-agency.html",seed:0.19,isWeval:true},
{name:"Wevia WL",cat:"weval",quad:"ai",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/wevia-whitelabel.html",seed:0.52,isWeval:true},
{name:"MailWarm",cat:"weval",quad:"tic",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/mailwarm.html",seed:0.26,isWeval:true},
{name:"MailForge",cat:"weval",quad:"tic",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/mailforge.html",seed:0.17,isWeval:true},
{name:"OutreachAI",cat:"weval",quad:"tic",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/outreachai.html",seed:0.86,isWeval:true},
{name:"AI SDR Agent",cat:"weval",quad:"tic",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/ai-sdr.html",seed:0.83,isWeval:true},
{name:"DeliverScore",cat:"weval",quad:"tic",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/deliverscore.html",seed:0.85,isWeval:true},
{name:"Email WL",cat:"weval",quad:"tic",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/email-whitelabel.html",seed:0.34,isWeval:true},
{name:"AdsControl",cat:"weval",quad:"tic",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/adscontrol.html",seed:0.56,isWeval:true},
{name:"MailStream",cat:"weval",quad:"tic",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/mailstream.html",seed:0.31,isWeval:true},
{name:"MedReach",cat:"weval",quad:"business",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/medreach.html",seed:0.47,isWeval:true},
{name:"MedReach API",cat:"weval",quad:"business",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/medreach-api.html",seed:0.76,isWeval:true},
{name:"MedReach HCP",cat:"weval",quad:"business",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/medreachhcp.html",seed:0.15,isWeval:true},
{name:"LeadForge",cat:"weval",quad:"business",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/leadforge.html",seed:0.15,isWeval:true},
{name:"DataHarvest",cat:"weval",quad:"business",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/dataharvest.html",seed:0.54,isWeval:true},
{name:"Healthcare CRM",cat:"weval",quad:"business",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/healthcare-crm.html",seed:0.46,isWeval:true},
{name:"CloudBridge",cat:"weval",quad:"infra",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/cloud-providers.html",seed:0.14,isWeval:true},
{name:"Consulting Pro",cat:"weval",quad:"business",status:"recommend",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/consulting.html",seed:0.9,isWeval:true},
{name:"ProposalAI",cat:"weval",quad:"ai",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/proposalai.html",seed:0.91,isWeval:true},
{name:"BlueprintAI",cat:"weval",quad:"ai",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/blueprintai.html",seed:0.43,isWeval:true},
{name:"CanvasAI",cat:"weval",quad:"ai",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/canvasai.html",seed:0.51,isWeval:true},
{name:"CopyAI",cat:"weval",quad:"ai",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/copyai.html",seed:0.43,isWeval:true},
{name:"PresentationAI",cat:"weval",quad:"ai",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/presentationai.html",seed:0.7,isWeval:true},
{name:"TranslateAI",cat:"weval",quad:"ai",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/translateai.html",seed:0.39,isWeval:true},
{name:"Business Plan",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/bizplan.html",seed:0.6,isWeval:true},
{name:"ContractAI",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/contractai.html",seed:0.39,isWeval:true},
{name:"Meeting Summary",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/meetingai.html",seed:0.78,isWeval:true},
{name:"eSignature",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/esignature.html",seed:0.45,isWeval:true},
{name:"Lean Six Sigma",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/leansixsigma.html",seed:0.79,isWeval:true},
{name:"Audit Compliance",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/auditai.html",seed:0.39,isWeval:true},
{name:"DashboardAI",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/dashboardai.html",seed:0.7,isWeval:true},
{name:"Academy",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/academy.html",seed:0.36,isWeval:true},
{name:"Weval CRM",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/wevalcrm.html",seed:0.67,isWeval:true},
{name:"Partner Program",cat:"weval",quad:"business",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/affiliates.html",seed:0.16,isWeval:true},
{name:"EmailVerify",cat:"weval",quad:"tic",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/emailverify.html",seed:0.69,isWeval:true},
{name:"InboxTest",cat:"weval",quad:"tic",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/inboxtest.html",seed:0.42,isWeval:true},
{name:"Network Monitor",cat:"weval",quad:"tic",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/ispmonitor.html",seed:0.19,isWeval:true},
{name:"NewsletterInsight",cat:"weval",quad:"tic",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/newsletterinsight.html",seed:0.29,isWeval:true},
{name:"NetworkGuard",cat:"weval",quad:"tic",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/blacklistguard.html",seed:0.3,isWeval:true},
{name:"SMSForge",cat:"weval",quad:"tic",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/smsforge.html",seed:0.45,isWeval:true},
{name:"ReputationAI",cat:"weval",quad:"tic",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/reputationai.html",seed:0.87,isWeval:true},
{name:"DevForge AI",cat:"weval",quad:"infra",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/devforge.html",seed:0.18,isWeval:true},
{name:"Wedroid",cat:"weval",quad:"infra",status:"use",stars:0,lang:"PHP",license:"Proprietary",replaces:"DevOps Agents",desc:"Autonomous DevOps AI agent — chain-of-thought, self-healing, 12 infra patterns, multi-server execution",descFr:"Agent IA DevOps autonome — chain-of-thought, self-healing, 12 patterns infra, exécution multi-serveur",url:"/products/wevalmind.html",seed:0.59,isWeval:true},
{name:"Creative Factory",cat:"weval",quad:"infra",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/creativefactory.html",seed:0.65,isWeval:true},
{name:"Scout Intelligence",cat:"weval",quad:"infra",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/scoutai.html",seed:0.12,isWeval:true},
{name:"YouTube Factory",cat:"weval",quad:"infra",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/youtubefactory.html",seed:0.64,isWeval:true},
{name:"StoreForge",cat:"weval",quad:"infra",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/storeforge.html",seed:0.12,isWeval:true},
{name:"FormBuilder",cat:"weval",quad:"infra",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/formbuilder.html",seed:0.87,isWeval:true},
{name:"StoreAI",cat:"weval",quad:"infra",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/storeai.html",seed:0.65,isWeval:true},
{name:"CloudCost",cat:"weval",quad:"infra",status:"explore",stars:0,lang:"PHP",license:"Proprietary",replaces:"WEVAL SaaS",desc:"WEVAL sovereign SaaS product",descFr:"Produit SaaS souverain WEVAL",url:"/products/cloudcost.html",seed:0.4,isWeval:true}].forEach(function(w){TOOLS.push(w)});
// Auto-discovered 2026-03-16 (10 tools)
[{name:"langchain",cat:"ai",quad:"ai",status:"use",stars:129624,lang:"Python",license:"MIT",replaces:"",desc:"The agent engineering platform",descFr:"The agent engineering platform",url:"https://github.com/langchain-ai/langchain",seed:0.3},{name:"open-webui",cat:"ai",quad:"ai",status:"use",stars:127333,lang:"Python",license:"NOASSERTION",replaces:"",desc:"User-friendly AI Interface (Supports Ollama, OpenAI API, ...)",descFr:"User-friendly AI Interface (Supports Ollama, OpenAI API, ...)",url:"https://github.com/open-webui/open-webui",seed:0.19},{name:"kubernetes",cat:"devops",quad:"infra",status:"use",stars:121168,lang:"Go",license:"Apache-2.0",replaces:"",desc:"Production-Grade Container Scheduling and Management",descFr:"Production-Grade Container Scheduling and Management",url:"https://github.com/kubernetes/kubernetes",seed:0.31},{name:"générative-ai-for-beginners",cat:"ai",quad:"ai",status:"use",stars:108065,lang:"Jupyter Notebook",license:"MIT",replaces:"",desc:"21 Lessons, Get Started Building with Générative AI ",descFr:"21 Lessons, Get Started Building with Générative AI ",url:"https://github.com/microsoft/générative-ai-for-beginners",seed:0.77},{name:"awesome-llm-apps",cat:"ai",quad:"ai",status:"use",stars:102253,lang:"Python",license:"Apache-2.0",replaces:"",desc:"Collection of awesome LLM apps with AI Agents and RAG using OpenAI, Anthropic, G",descFr:"Collection of awesome LLM apps with AI Agents and RAG using OpenAI, Anthropic, G",url:"https://github.com/Shubhamsaboo/awesome-llm-apps",seed:0.64},{name:"immich",cat:"devops",quad:"infra",status:"use",stars:94838,lang:"TypeScript",license:"AGPL-3.0",replaces:"",desc:"High performance self-hosted photo and video management solution.",descFr:"High performance self-hosted photo and video management solution.",url:"https://github.com/immich-app/immich",seed:0.92},{name:"firecrawl",cat:"ai",quad:"ai",status:"use",stars:93548,lang:"TypeScript",license:"AGPL-3.0",replaces:"",desc:"🔥 The Web Data API for AI - Turn entire websites into LLM-ready markdown or stru",descFr:"🔥 The Web Data API for AI - Turn entire websites into LLM-ready markdown or stru",url:"https://github.com/firecrawl/firecrawl",seed:0.31},{name:"uptime-kuma",cat:"devops",quad:"infra",status:"use",stars:84112,lang:"JavaScript",license:"MIT",replaces:"",desc:"A fancy self-hosted monitoring tool",descFr:"A fancy self-hosted monitoring tool",url:"https://github.com/louislam/uptime-kuma",seed:0.68},{name:"devops-exercises",cat:"devops",quad:"infra",status:"use",stars:81504,lang:"Python",license:"NOASSERTION",replaces:"",desc:"Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, ",descFr:"Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, ",url:"https://github.com/bregman-arie/devops-exercises",seed:0.59},{name:"browser-use",cat:"ai",quad:"ai",status:"use",stars:80872,lang:"Python",license:"MIT",replaces:"",desc:"🌐 Make websites accessible for AI agents. Automate tasks online with ease.",descFr:"🌐 Make websites accessible for AI agents. Automate tasks online with ease.",url:"https://github.com/browser-use/browser-use",seed:0.09}].forEach(function(w){TOOLS.push(w)});
const TOOL_LOGOS = {"AI SDR Agent": "/assets/logo-outreachai.svg", "Academy": "/assets/logo-academy.svg", "AdsControl": "/assets/logo-adscontrol.svg", "Audit Compliance": "/assets/logo-auditcompliance.svg", "Authentik": "https://github.com/goauthentik.png?size=40", "BlueprintAI": "/assets/logo-blueprintai.svg", "Business Plan": "/assets/logo-bizplan.svg", "CanvasAI": "/assets/logo-canvasai.svg", "CloudBridge": "/assets/logo-cloudbridge.svg", "CloudCost": "/assets/logo-cloudcost.svg", "ComfyUI": "https://github.com/comfyanonymous.png?size=40", "Consulting": "/assets/logo-consulting.svg", "Consulting Pro": "/assets/logo-consulting.svg", "Content Factory": "/assets/logo-content-factory.svg", "ContractAI": "/assets/logo-contractai.svg", "Coolify": "https://github.com/coollabsio.png?size=40", "CopyAI": "/assets/logo-copyai.svg", "Creative Factory": "/assets/logo-creative-factory.svg", "CrowdSec": "https://github.com/crowdsecurity.png?size=40", "DashboardAI": "/assets/logo-dashboardai.svg", "DataHarvest": "/assets/logo-dataharvest.svg", "DeliverAds": "/assets/logo-deliverads.svg", "DeliverScore": "/assets/logo-deliverscore.svg", "DevForge AI": "/assets/logo-devforge.svg", "Dify": "https://github.com/langgenius.png?size=40", "Digital Platform": "/assets/logo-wevads-Crayl4yz.png", "ERPNext": "https://github.com/frappe.png?size=40", "Email WL": "/assets/logo-mailforge.svg", "EmailVerify": "/assets/logo-emailverify.svg", "FormBuilder": "/assets/logo-formbuilder.svg", "Gitea": "https://github.com/go-gitea.png?size=40", "Grafana": "https://github.com/grafana.png?size=40", "Healthcare CRM": "/assets/logo-medreach.svg", "IA Arabe FR": "/assets/logo-wevia-official.svg", "InboxTest": "/assets/logo-inboxtest.svg", "Langflow": "https://github.com/langflow-ai.png?size=40", "LeadForge": "/assets/logo-leadforge.svg", "Lean Six Sigma": "/assets/logo-leansixsigma.svg", "Listmonk": "https://raw.githubusercontent.com/knadh/listmonk/master/static/public/static/logo.svg", "MailForge": "/assets/logo-mailforge.svg", "MailStream": "/assets/logo-mailstream.svg", "MailWarm": "/assets/logo-mailwarm.svg", "Mautic": "https://github.com/mautic.png?size=40", "MedReach": "/assets/logo-medreach.svg", "MedReach API": "/assets/logo-medreach.svg", "MedReach HCP": "/assets/logo-medreach.svg", "Meeting Summary": "/assets/logo-meeting-summary.svg", "Metabase": "https://github.com/metabase.png?size=40", "Network Monitor": "/assets/logo-ispmonitor.svg", "NetworkGuard": "/assets/logo-sentinel.svg", "NewsletterInsight": "/assets/logo-newsletter.svg", "Ollama": "https://github.com/ollama.png?size=40", "Open WebUI": "https://github.com/open-webui.png?size=40", "Outline": "https://github.com/outline.png?size=40", "OutreachAI": "/assets/logo-outreachai.svg", "Partner Program": "/assets/logo-affiliates.svg", "Plane": "https://github.com/makeplane.png?size=40", "Plausible": "https://github.com/plausible.png?size=40", "PostHog": "https://github.com/PostHog.png?size=40", "Postal": "https://github.com/postalserver.png?size=40", "PresentationAI": "/assets/logo-presentationai.svg", "ProposalAI": "/assets/logo-proposalai.svg", "Qdrant": "https://github.com/qdrant.png?size=40", "ReputationAI": "/assets/logo-reputationai.svg", "SMSForge": "/assets/logo-smsforge.svg", "Scout Intelligence": "/assets/logo-scout.svg", "SearXNG": "https://github.com/searxng.png?size=40", "Sentinel": "/assets/logo-sentinel.svg", "StoreAI": "/assets/logo-storeforge.svg", "StoreForge": "/assets/logo-storeforge.svg", "Supabase": "https://github.com/supabase.png?size=40", "Superset": "https://github.com/apache.png?size=40", "Traefik": "https://github.com/traefik.png?size=40", "TranslateAI": "/assets/logo-translateai.svg", "Twenty CRM": "https://github.com/twentyhq.png?size=40", "Uptime Kuma": "https://github.com/louislam.png?size=40", "WEVADS": "/assets/logo-wevads-Crayl4yz.png", "WEVAL Mind": "/assets/logo-weval-mind.svg", "WEVIA Agency": "/assets/logo-wevia-official.svg", "WEVIA Enterprise": "/assets/logo-wevia-official.svg", "Wazuh": "https://github.com/wazuh.png?size=40", "Wevads IA": "/assets/logo-wevads-Crayl4yz.png", "Weval CRM": "/assets/logo-weval-crm.svg", "Wevanalytics": "/assets/logo-wevanalytics.svg", "Wevia Inference": "/assets/logo-wevia-official.svg", "Wevia WL": "/assets/logo-wevia-official.svg", "YouTube Factory": "/assets/logo-youtube-factory.svg", "browser-use": "https://github.com/browser-use.png?size=40", "eSignature": "/assets/logo-esignature.svg", "firecrawl": "https://github.com/mendableai.png?size=40", "frp": "https://github.com/fatedier.png?size=40", "immich": "https://github.com/immich-app.png?size=40", "kubernetes": "https://github.com/kubernetes.png?size=40", "langchain": "https://github.com/langchain-ai.png?size=40", "n8n": "https://github.com/n8n-io.png?size=40", "vLLM": "https://github.com/vllm-project.png?size=40"};
TOOLS.sort(function(a,b){var q={ai:0,tic:1,business:2,infra:3};var s={use:0,recommend:1,explore:2};return (q[a.quad]||9)-(q[b.quad]||9)||(s[a.status]||9)-(s[b.status]||9)});
let lang = "en", activeCat = "all", activeStatus = null, hoveredBlip = null, selectedTool = null;
function t(en, fr) { return lang === "fr" ? fr : en; }
function fmtStars(n) { return n >= 100000 ? Math.round(n/1000)+"K" : n >= 1000 ? (n/1000).toFixed(1)+"K" : n; }
function toggleLang() {
lang = lang === "en" ? "fr" : "en";
document.getElementById("langBtn").textContent = lang === "en" ? "FR" : "EN";
document.getElementById("title").textContent = t("Our Open Source Arsenal", "Notre Arsenal Open Source");
document.getElementById("subtitle").textContent = t("The sovereign tools we deploy, recommend, and explore for our clients.", "Les outils souverains que nous déployons, recommandons et explorons.");
document.getElementById("langTitle").textContent = t("Primary Languages", "Langages principaux");
document.getElementById("searchInput").placeholder = t("Search tool or product...", "Rechercher outil ou produit...");
document.getElementById("footerText").textContent = "WEVAL Consulting · Casablanca · " + t("Digital Sovereignty", "Souveraineté numérique") + " · 2026";
buildRadar(); buildLegend(); buildCatBtns(); render();
}
// ═══════════════════════════════════
// RADAR SVG
// ═══════════════════════════════════
function buildRadar() {
const S = 560, cx = 280, cy = 280, maxR = 240;
const rings = [maxR*.32, maxR*.62, maxR*.90];
const ringLbls = [t("WE USE","ON UTILISE"), t("RECOMMEND","ON RECOMMANDE"), t("EXPLORE","ON EXPLORE")];
let svg = `<defs>
<radialGradient id="rg"><stop offset="0%" stop-color="#151722"/><stop offset="100%" stop-color="#0A0B0F"/></radialGradient>
<linearGradient id="sweep" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#00E5A0" stop-opacity=".3"/><stop offset="100%" stop-color="#00E5A0" stop-opacity="0"/></linearGradient>
</defs>`;
// Background
svg += `<circle cx="${cx}" cy="${cy}" r="${maxR+8}" fill="url(#rg)"/>`;
// Sweep line
svg += `<line x1="${cx}" y1="${cy}" x2="${cx}" y2="${cy-maxR}" stroke="url(#sweep)" stroke-width="2" class="radar-sweep"/>`;
// Rings
rings.forEach((r, i) => {
const dash = i === 2 ? ' stroke-dasharray="5 5"' : '';
svg += `<circle cx="${cx}" cy="${cy}" r="${r}" fill="none" stroke="#1C1F2E" stroke-width="1"${dash}/>`;
});
// Ring labels
ringLbls.forEach((lbl, i) => {
svg += `<text x="${cx+6}" y="${cy-rings[i]+14}" fill="#252840" font-size="7.5" font-family="'JetBrains Mono',monospace" letter-spacing="1.2">${lbl}</text>`;
});
// Axis lines
svg += `<line x1="${cx}" y1="${cy-maxR-4}" x2="${cx}" y2="${cy+maxR+4}" stroke="#1C1F2E" stroke-width=".8"/>`;
svg += `<line x1="${cx-maxR-4}" y1="${cy}" x2="${cx+maxR+4}" y2="${cy}" stroke="#1C1F2E" stroke-width=".8"/>`;
// Quadrant labels
QUADRANTS.forEach((q, i) => {
const a = i * Math.PI/2 - Math.PI/4;
const lr = maxR + 22;
const lx = cx + lr * Math.cos(a), ly = cy + lr * Math.sin(a);
const lbl = lang === "fr" ? q.labelFr : q.label;
svg += `<text x="${lx}" y="${ly}" fill="${QC[i]}" font-size="8.5" font-weight="600" text-anchor="middle" dominant-baseline="middle" font-family="'DM Sans',sans-serif" style="text-transform:uppercase;letter-spacing:1.5px">${lbl}</text>`;
});
// Center
svg += `<circle cx="${cx}" cy="${cy}" r="18" fill="#12141E" stroke="#1C1F2E" stroke-width="1"/>`;
svg += `<text x="${cx}" y="${cy+1}" fill="#00E5A0" font-size="12" font-weight="700" text-anchor="middle" dominant-baseline="middle" font-family="'DM Sans',sans-serif">W</text>`;
// Blips — Pass 1: compute positions
const blipPos = [];
TOOLS.forEach((tool, idx) => {
const qi = QUADRANTS.findIndex(q => q.id === tool.quad);
const ri = STATUSES[tool.status].ring;
const innerR = ri === 0 ? 22 : rings[ri-1] + 8;
const outerR = rings[ri] - 8;
const r = innerR + (outerR - innerR) * (.15 + tool.seed * .7);
const base = qi * Math.PI/2 - Math.PI/2;
const a = base + .12 + (Math.PI/2 - .24) * ((tool.seed + idx * 0.017) % 1);
blipPos.push({px: cx + r * Math.cos(a), py: cy + r * Math.sin(a), tool, qi, idx});
});
// Pass 2: force-repel overlapping blips (5 iterations)
for (let iter = 0; iter < 5; iter++) {
for (let i = 0; i < blipPos.length; i++) {
for (let j = i + 1; j < blipPos.length; j++) {
const dx = blipPos[j].px - blipPos[i].px;
const dy = blipPos[j].py - blipPos[i].py;
const dist = Math.sqrt(dx*dx + dy*dy);
const minDist = 14;
if (dist < minDist && dist > 0) {
const force = (minDist - dist) / 2;
const fx = (dx / dist) * force;
const fy = (dy / dist) * force;
blipPos[i].px -= fx; blipPos[i].py -= fy;
blipPos[j].px += fx; blipPos[j].py += fy;
}
}
}
}
// Pass 3: render
blipPos.forEach(({px, py, tool, qi}) => {
const _px = px, _py = py;
const col = tool.isWeval ? "#14B8A6" : QC[qi];
const tid = tool.name.replace(/\s/g, "-");
const labelX = _px > cx ? _px + 12 : _px - tool.name.length * 6.5 - 20;
svg += `<g class="blip" data-name="${tool.name}" onmouseenter="hoverBlip('${tid}')" onmouseleave="unhoverBlip()" onclick="selectBlip('${tid}')">`;
svg += `<circle class="blip-glow" cx="${_px}" cy="${_py}" r="16" fill="${col}" opacity="0"/>`;
svg += `<circle class="blip-dot" cx="${_px}" cy="${_py}" r="5.5" fill="${col}" opacity=".85"/>`;
svg += `<g class="blip-label"><rect x="${labelX}" y="${_py-13}" width="${tool.name.length*6.5+18}" height="22" rx="5" fill="#1A1D2A" stroke="${col}" stroke-width=".6" opacity=".96"/><text x="${labelX+9}" y="${_py+1}" fill="#fff" font-size="10.5" font-weight="500" font-family="'DM Sans',sans-serif">${tool.name}</text></g>`;
svg += `</g>`;
});
document.getElementById("radarSvg").innerHTML = svg;
setTimeout(function(){document.querySelectorAll(".blip").forEach(function(g){var n=g.getAttribute("data-name");if(n){var t=TOOLS.find(function(x){return x.name===n});if(t&&t.isWeval){var d=g.querySelector(".blip-dot");if(d)d.classList.add("weval-dot")}}})},100);
}
function hoverBlip(tid) { hoveredBlip = tid; }
function unhoverBlip() { hoveredBlip = null; }
function selectBlip(tid) {
const el = document.getElementById("card-" + tid);
if (el) el.scrollIntoView({behavior:"smooth", block:"center"});
}
// ═══════════════════════════════════
// LEGEND
// ═══════════════════════════════════
function buildLegend() {
const totalStars = TOOLS.reduce((a,t) => a+t.stars, 0);
const langStats = {};
TOOLS.forEach(t => { langStats[t.lang] = (langStats[t.lang]||0)+1; });
const sc = {use:0,recommend:0,explore:0};
TOOLS.forEach(t => sc[t.status]++);
let h = '';
// Quadrants
h += `<div class="legend-section"><div class="legend-title mono">Quadrants</div>`;
QUADRANTS.forEach((q,i) => {
const cnt = TOOLS.filter(t => t.quad === q.id).length;
h += `<div class="legend-row"><span class="legend-dot" style="background:${QC[i]}"></span><span class="legend-label">${lang==="fr"?q.labelFr:q.label}</span><span class="legend-count mono">${cnt}</span></div>`;
});
const wCnt = TOOLS.filter(t => t.isWeval).length;
h += `<div class="legend-row"><span class="legend-dot" style="background:#14B8A6"></span><span class="legend-label">WEVAL SaaS</span><span class="legend-count mono">${wCnt}</span></div>`;
h += `</div>`;
// Rings
h += `<div class="legend-section"><div class="legend-title mono">${t("Rings","Anneaux")}</div>`;
Object.entries(STATUSES).forEach(([k,v]) => {
const active = activeStatus === k;
h += `<div class="legend-row" onclick="toggleStatus('${k}')"><div class="ring-dot ${active?'active':''}" style="color:${v.color};border-color:${v.color}"></div><span class="legend-label" style="color:${active?v.color:'#C8CAD4'}">${lang==="fr"?v.labelFr:v.label}</span><span class="legend-count mono">${sc[k]}</span></div>`;
});
h += `</div>`;
// Stats
h += `<div class="stats-box">`;
h += `<div class="stats-row"><span class="stats-label">${t("Curated tools","Outils curatés")}</span><span class="stats-val" style="color:var(--green)">${TOOLS.length}</span></div>`;
h += `<div class="stats-row"><span class="stats-label">GitHub Stars</span><span class="stats-val" style="color:var(--yellow)">${(totalStars/1e6).toFixed(1)}M</span></div>`;
h += `<div class="stats-row"><span class="stats-label">${t("Languages","Langages")}</span><span class="stats-val" style="color:var(--blue)">${Object.keys(langStats).length}</span></div>`;
h += `</div>`;
document.getElementById("radarLegend").innerHTML = h;
}
function toggleStatus(k) {
activeStatus = activeStatus === k ? null : k;
buildLegend(); render();
}
// ═══════════════════════════════════
// LANGUAGE BAR
// ═══════════════════════════════════
function buildLangBar() {
const stats = {};
TOOLS.forEach(t => { stats[t.lang] = (stats[t.lang]||0)+1; });
const sorted = Object.entries(stats).sort((a,b) => b[1]-a[1]).slice(0,6);
let bar = '', labels = '';
sorted.forEach(([l,c]) => {
bar += `<div class="lang-segment" style="flex:${c};background:${LC[l]||'#666'}"></div>`;
labels += `<div class="lang-item"><div class="lang-dot" style="background:${LC[l]||'#666'}"></div><span style="color:#8B8FA3">${l}</span><span class="mono" style="color:var(--muted);font-size:11px">${Math.round(c/TOOLS.length*100)}%</span></div>`;
});
document.getElementById("langBar").innerHTML = bar;
document.getElementById("langLabels").innerHTML = labels;
}
// ═══════════════════════════════════
// CATEGORY BUTTONS
// ═══════════════════════════════════
function buildCatBtns() {
let h = '';
CATEGORIES.forEach(c => {
const active = activeCat === c.id ? ' active' : '';
const lbl = lang === "fr" ? c.labelFr : c.label;
h += `<button class="cat-btn${active}" onclick="setCat('${c.id}')">${c.icon} ${lbl}</button>`;
});
document.getElementById("catBtns").innerHTML = h;
}
function setCat(id) { activeCat = id; buildCatBtns(); render(); }
// ═══════════════════════════════════
// CARDS
// ═══════════════════════════════════
function render() {
const q = document.getElementById("searchInput").value.toLowerCase();
const filtered = TOOLS.filter(tool => {
if (activeCat !== "all" && tool.cat !== activeCat) return false;
if (activeStatus && tool.status !== activeStatus) return false;
if (q) return tool.name.toLowerCase().includes(q) || tool.replaces.toLowerCase().includes(q) || tool.desc.toLowerCase().includes(q);
return true;
});
document.getElementById("resultCount").textContent = filtered.length + " " + t("results","résultats") + (activeStatus ? " · " + (lang==="fr" ? STATUSES[activeStatus].labelFr : STATUSES[activeStatus].label) : "");
let h = '';
filtered.forEach((tool, i) => {
const st = STATUSES[tool.status];
const tid = tool.name.replace(/\s/g, "-");
const delay = Math.min(i * .04, .4);
const desc = lang === "fr" ? tool.descFr : tool.desc;
const stLabel = lang === "fr" ? st.labelFr : st.label;
const wc = tool.isWeval ? " weval-card" : "";
h += `<div class="tool-card${wc} fade-up" id="card-${tid}" style="--sc:${st.color};animation-delay:${delay}s" onclick="window.open('${tool.url}','_blank')">`;
h += `<div class="card-top"><div>`;
h += `<div style="display:flex;align-items:center;gap:8px;margin-bottom:4px">`;
const logoUrl = TOOL_LOGOS[tool.name] || "";
if(logoUrl){h += `<img class="card-logo" src="${logoUrl}" alt="" onerror="this.style.display='none'">`}
h += `<span class="card-name">${tool.name}</span>`;
h += `<span class="status-pill" style="background:${st.color}12;color:${st.color};border:1px solid ${st.color}25"><span class="status-dot${tool.status==='use'?' pulse':''}" style="background:${st.color}"></span>${stLabel}</span>`;
h += `</div>`;
h += `<span class="replaces-badge">↔ ${tool.replaces}</span>`;
h += `</div>`;
if(tool.isWeval){h+=`<div class="card-stars"><div class="card-stars-num" style="color:#14B8A6;font-size:13px">SaaS</div><div class="card-stars-label" style="color:#14B8A6">WEVAL</div></div>`}else{h += `<div class="card-stars"><div class="card-stars-num">${fmtStars(tool.stars)}</div><div class="card-stars-label">★ stars</div></div>`;}
h += `</div>`;
h += `<p class="card-desc">${desc}</p>`;
h += `<div class="card-footer"><div style="display:flex;gap:8px;align-items:center">`;
h += `<span class="card-lang mono"><span class="lang-dot" style="background:${LC[tool.lang]||'#666'}"></span>${tool.lang}</span>`;
h += `<span class="card-license mono">${tool.license}</span>`;
h += `</div><svg class="card-arrow" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M7 17L17 7M17 7H7M17 7V17"/></svg></div>`;
h += `</div>`;
});
document.getElementById("cardsGrid").innerHTML = h;
}
// Init
buildRadar();
buildLegend();
buildLangBar();
buildCatBtns();
render();
</script>
<!-- AUTO-DISCOVERY INJECTION (enrichment, not replacement) -->
<script id="oss-auto-discovery">
(function(){
// Tools discovered by Opus analysis — inject into radar if not already present
var newTools = [
{name:"Langfuse",stars:"23K",cat:"🧠 Sovereign AI",status:"We Recommend",alt:"LangSmith",desc:"LLM observability — tracing, eval, prompt versioning",lang:"TypeScript",license:"MIT",gh:"langfuse/langfuse"},
{name:"RAGFlow",stars:"65K",cat:"🧠 Sovereign AI",status:"Exploring",alt:"Coveo/Elastic",desc:"Deep document parsing + GraphRAG",lang:"Python",license:"Apache-2.0",gh:"infiniflow/ragflow"},
{name:"Unsloth",stars:"54K",cat:"🧠 Sovereign AI",status:"Exploring",alt:"AWS Bedrock",desc:"2× faster fine-tuning, 70% less VRAM",lang:"Python",license:"Apache-2.0",gh:"unslothai/unsloth"},
{name:"LLaMA-Factory",stars:"60K",cat:"🧠 Sovereign AI",status:"Exploring",alt:"Vertex AI",desc:"Zero-code fine-tuning 100+ models",lang:"Python",license:"Apache-2.0",gh:"hiyouga/LLaMA-Factory"},
{name:"CrewAI",stars:"39K",cat:"🧠 Sovereign AI",status:"Exploring",alt:"Custom agents",desc:"Multi-agent orchestration",lang:"Python",license:"MIT",gh:"crewAIInc/crewAI"},
{name:"Whisper.cpp",stars:"37K",cat:"🧠 Sovereign AI",status:"We Recommend",alt:"Google STT",desc:"CPU speech-to-text, zero API cost",lang:"C++",license:"MIT",gh:"ggerganov/whisper.cpp"},
{name:"ArgoCD",stars:"22K",cat:"⚙ DevOps & Infra",status:"We Recommend",alt:"Harness CD",desc:"GitOps standard, CNCF graduated",lang:"Go",license:"Apache-2.0",gh:"argoproj/argo-cd"},
{name:"Harbor",stars:"28K",cat:"⚙ DevOps & Infra",status:"We Recommend",alt:"Docker Hub",desc:"CNCF container registry + scanning",lang:"Go",license:"Apache-2.0",gh:"goharbor/harbor"},
{name:"Grafana Loki",stars:"28K",cat:"⚙ DevOps & Infra",status:"We Recommend",alt:"ELK/Splunk",desc:"Log aggregation for Grafana",lang:"Go",license:"AGPL-3.0",gh:"grafana/loki"},
{name:"SigNoz",stars:"25K",cat:"⚙ DevOps & Infra",status:"Exploring",alt:"Datadog",desc:"OpenTelemetry APM+traces+logs",lang:"TypeScript",license:"MIT",gh:"SigNoz/signoz"},
{name:"Infisical",stars:"25K",cat:"🛡 Security",status:"We Recommend",alt:"Vault",desc:"Modern secrets management",lang:"TypeScript",license:"MIT",gh:"Infisical/infisical"},
{name:"OpenTofu",stars:"28K",cat:"⚙ DevOps & Infra",status:"We Recommend",alt:"Terraform",desc:"Linux Foundation Terraform fork",lang:"Go",license:"MPL-2.0",gh:"opentofu/opentofu"},
{name:"Velero",stars:"9.2K",cat:"⚙ DevOps & Infra",status:"We Recommend",alt:"Kasten K10",desc:"K8s backup + disaster recovery",lang:"Go",license:"Apache-2.0",gh:"vmware-tanzu/velero"},
{name:"Twenty CRM",stars:"37K",cat:"📊 Business Apps",status:"We Recommend",alt:"Salesforce",desc:"Modern CRM, GraphQL, Notion-like UX",lang:"TypeScript",license:"AGPL-3.0",gh:"twentyhq/twenty"},
{name:"Plane",stars:"40K",cat:"📊 Business Apps",status:"We Recommend",alt:"Jira/Linear",desc:"Project mgmt — sprints, AI pages",lang:"TypeScript",license:"AGPL-3.0",gh:"makeplane/plane"},
{name:"Cal.com",stars:"39K",cat:"📊 Business Apps",status:"We Recommend",alt:"Booking WEVAL",desc:"Scheduling infra, team booking",lang:"TypeScript",license:"AGPL-3.0",gh:"calcom/cal.com"},
{name:"Chatwoot",stars:"28K",cat:"📊 Business Apps",status:"We Recommend",alt:"Intercom/Zendesk",desc:"Omnichannel support",lang:"Ruby",license:"MIT",gh:"chatwoot/chatwoot"},
{name:"NocoDB",stars:"50K",cat:"📊 Business Apps",status:"We Recommend",alt:"Airtable",desc:"SQL→spreadsheet, API-first",lang:"TypeScript",license:"AGPL-3.0",gh:"nocodb/nocodb"},
{name:"ClickHouse",stars:"39K",cat:"📈 Data & Analytics",status:"We Recommend",alt:"Snowflake/BigQuery",desc:"OLAP billions rows/sec",lang:"C++",license:"Apache-2.0",gh:"ClickHouse/ClickHouse"},
{name:"Airbyte",stars:"21K",cat:"📈 Data & Analytics",status:"We Recommend",alt:"Fivetran",desc:"600+ connectors data integration",lang:"Java",license:"MIT",gh:"airbytehq/airbyte"},
{name:"PostHog",stars:"25K",cat:"📈 Data & Analytics",status:"Exploring",alt:"Mixpanel+Hotjar",desc:"Product analytics+session replay",lang:"Python",license:"MIT",gh:"PostHog/posthog"},
{name:"Mattermost",stars:"36K",cat:"📊 Business Apps",status:"We Recommend",alt:"Slack/Teams",desc:"Enterprise team messaging",lang:"Go",license:"MIT",gh:"mattermost/mattermost"},
{name:"Jitsi Meet",stars:"29K",cat:"📊 Business Apps",status:"We Recommend",alt:"Zoom",desc:"Browser video conferencing",lang:"Java",license:"Apache-2.0",gh:"jitsi/jitsi-meet"},
{name:"Vaultwarden",stars:"57K",cat:"🛡 Security",status:"We Recommend",alt:"1Password",desc:"Bitwarden-compatible, 256MB RAM",lang:"Rust",license:"AGPL-3.0",gh:"dani-garcia/vaultwarden"},
{name:"Trivy",stars:"25K",cat:"🛡 Security",status:"We Recommend",alt:"Snyk/Qualys",desc:"Container+IaC vulnerability scanner",lang:"Go",license:"Apache-2.0",gh:"aquasecurity/trivy"},
{name:"Gitleaks",stars:"25K",cat:"🛡 Security",status:"We Recommend",alt:"GitGuardian",desc:"Detect secrets in git repos",lang:"Go",license:"MIT",gh:"gitleaks/gitleaks"},
{name:"Nuclei",stars:"27K",cat:"🛡 Security",status:"Exploring",alt:"Nessus",desc:"12K+ templates vuln scanner",lang:"Go",license:"MIT",gh:"projectdiscovery/nuclei"},
{name:"Excalidraw",stars:"119K",cat:"📊 Business Apps",status:"We Use",alt:"Miro/FigJam",desc:"Collaborative whiteboard",lang:"TypeScript",license:"MIT",gh:"excalidraw/excalidraw"},
{name:"MLflow",stars:"19K",cat:"🧠 Sovereign AI",status:"We Recommend",alt:"W&B/Neptune",desc:"MLOps lifecycle management",lang:"Python",license:"Apache-2.0",gh:"mlflow/mlflow"},
{name:"Haystack",stars:"23K",cat:"🧠 Sovereign AI",status:"Exploring",alt:"Custom RAG",desc:"Production RAG framework",lang:"Python",license:"Apache-2.0",gh:"deepset-ai/haystack"},
];
// Wait for existing radar data, then inject missing
function injectTools() {
if(typeof window.ALL_TOOLS === "undefined") window.ALL_TOOLS = [];
var existingNames = window.ALL_TOOLS.map(function(t){ return t.name.toLowerCase(); });
var added = 0;
newTools.forEach(function(t) {
if(existingNames.indexOf(t.name.toLowerCase()) === -1) {
window.ALL_TOOLS.push(t);
added++;
}
});
if(added > 0 && typeof window.renderTools === "function") {
window.renderTools(window.ALL_TOOLS);
}
// Update counter
var counter = document.querySelector("[data-results-count],.results-count,#results-count");
if(counter) counter.textContent = window.ALL_TOOLS.length + " results";
console.log("OSS Discovery: injected " + added + " tools, total: " + window.ALL_TOOLS.length);
}
// Auto-run after page load
if(document.readyState === "complete") setTimeout(injectTools, 1000);
else window.addEventListener("load", function(){ setTimeout(injectTools, 1000); });
setTimeout(injectTools, 3000);
setTimeout(injectTools, 5000);
})();
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
<script>
(function(){
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
var d = document;
var m = d.createElement('div');
m.id = 'opus-udrill';
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
var inner = d.createElement('div');
inner.id = 'opus-udrill-in';
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
inner.addEventListener('click', function(e){ e.stopPropagation(); });
m.appendChild(inner);
m.addEventListener('click', function(){ m.style.display='none'; });
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
(d.body || d.documentElement).appendChild(m);
function openCard(card) {
// Clone card content + show close btn + increase font-size
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
inner.innerHTML = html;
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
m.style.display = 'flex';
}
function wire(root) {
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
var cards = root.querySelectorAll(sels);
for (var i = 0; i < cards.length; i++) {
var c = cards[i];
if (c.__opusWired) continue;
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
var r = c.getBoundingClientRect();
if (r.width < 60 || r.height < 40) continue;
c.__opusWired = true;
c.style.cursor = 'pointer';
c.setAttribute('role','button');
c.setAttribute('tabindex','0');
c.addEventListener('click', function(ev){
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
if (ev.target.closest('a,button,input,select')) return;
ev.preventDefault(); ev.stopPropagation();
openCard(this);
});
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
}
}
// Initial + mutation observer
var initRun = function(){ wire(d.body || d.documentElement); };
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
else initRun();
var mo = new MutationObserver(function(muts){
var newCard = false;
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
if (newCard) initRun();
});
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
})();
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
<script src="/api/a11y-auto-enhancer.js" defer></script>
</body>
</html>