// 05 Network — the hero. Four directions of the visualization. const NetworkTab = () => (
{/* Force-directed atlas */}
Strength: reads like an atlas; clusters legible at any zoom. Risk: mechanics need polish to avoid hairball at full scale.
Strength: encodes ecosystem position (research → bridge → practice) on the radius. Risk: rigid; less expressive for ad-hoc exploration.
Strength: personal, immediate “my neighbourhood”. Use as: default landing into network from a profile.
Strength: answers “who’s solving the same thing?” at a glance. Edges are pulsing red dashes.
{/* Side panel + path view */}
{/* light scatter behind */} {Array.from({length: 26}).map((_,i)=> { const x=20+Math.random()*420, y=20+Math.random()*320; return ; })}
forcecirclecluster
Selected · Project
HYDRO-NL Pilot
TRL 5 · NL · 7 members
complementary 88%
Why connected to you
  • Their need: membrane durability data
  • Your offer: membrane test method
  • Shared subdomain: PEM
  • Method overlap: LCA
Open match →
Show shortest path
You → Liesbeth → HYDRO-NL
2 hops · via Membranes domain
Show
{['Person','Project','Org','Domain','Method','Challenge','Bottleneck','Uncertainty'].map((t,i)=>(
{t}
))}
Relationship
{[['Similarity','#1c5fbf'],['Complementarity','#d96b2c'],['Anti-dup','#c33a3a'],['Bridge','#2a8a5c'],['Method transfer','#7a6cf0'],['Shared uncertainty','#c9a227']].map(([t,c],i)=>(
{t}
))}
Strength ≥
{[0.2,0.4,0.6,0.8].map(v=> {v})}
{[[60,80,'pj'],[120,40,'p'],[200,70,'p'],[260,40,'d'],[330,90,'p'],[300,170,'pj'],[230,200,'p'],[150,180,'me'],[80,210,'p'],[60,270,'o'],[170,260,'pj'],[280,260,'p'],[330,200,'d']].map(([x,y,k],i)=>{ const colors = {p:'#1c5fbf',pj:'#d96b2c',o:'#2a8a5c',d:'#b14fa6',me:'#1a1a1a'}; return })} {[[150,180,60,80],[150,180,120,40],[150,180,200,70],[150,180,300,170],[150,180,230,200],[150,180,80,210],[150,180,170,260],[200,70,260,40],[300,170,330,200],[300,170,280,260],[60,80,60,270]].map(([x1,y1,x2,y2],i)=>( ))}
62 nodes · 134 edges · zoom 1.0×
Toggle Anti-dup on → red dashed edges only. Toggle Bridge on → only cross-cluster edges. The graph stays meaningful at any filter combination.
{/* Need-Offer + Path */}
{/* needs side */} Needs Offers {[ ['Durability data',60, 'Membrane test method',60], ['Test bench',110, 'Lab access',120], ['Curriculum module',160, 'Teaching package',180], ['Industry partner',210, 'Pilot site',240], ['LCA expertise',260, 'LCA practitioner',280], ].map(([n,y1,o,y2],i) => ( {n} {o} ))}
Hover a flow → highlights both stakeholders. Strength = thickness.
{/* faint background nodes */} {Array.from({length:14}).map((_,i)=>( ))}
4 hops via PEM → Liesbeth → HYDRO-NL → Bram · total strength 0.78
); const NetworkChrome = ({modeLabel, children}) => (
ForceCircleClusterMap
layout
Search node{modeLabel && {modeLabel}}Save view
{children}
); const ForceAtlas = () => (
Production / Materials Projects / Pilots Orgs / Bridges Education / Domains {/* nodes */} {Array.from({length: 60}).map((_,i)=> { // distribute around clusters const cluster = i % 4; const cx = [160,430,460,220][cluster], cy = [140,120,260,290][cluster]; const a = Math.random()*Math.PI*2, r = 20 + Math.random()*70; const x = cx + Math.cos(a)*r, y = cy + Math.sin(a)*r; const colors = ['#1c5fbf','#d96b2c','#2a8a5c','#b14fa6']; const sz = 3 + Math.random()*4; return ; })} {/* edges */} {Array.from({length: 50}).map((_,i)=> { const x1=80+Math.random()*440, y1=40+Math.random()*280; const x2=80+Math.random()*440, y2=40+Math.random()*280; return ; })} {/* you */} You {/* recommended highlights */}
248 nodes · 4 clusters · zoom 0.8×
); const OrbitalLayout = () => (
{[60,110,160,210].map((r,i)=>( ))} core {/* ring labels */} research bridge practice policy {/* nodes scattered on rings */} {Array.from({length: 50}).map((_,i)=> { const ring = [60,110,160,210][i%4]; const a = (i/50)*Math.PI*2; const x = 300 + Math.cos(a)*ring, y = 180 + Math.sin(a)*ring; const colors = ['#1c5fbf','#d96b2c','#2a8a5c','#b14fa6']; return ; })} {/* you on ring 2 */} {/* radial highlights */} {[0.6,0.62,0.65].map((a,i)=>{ const x1 = 300+Math.cos(a)*60, y1=180+Math.sin(a)*60; const x2 = 300+Math.cos(a-0.05)*210, y2=180+Math.sin(a-0.05)*210; return ; })}
); const FocusMode = () => (
{/* you in centre */} You {/* 1-hop ring */} {Array.from({length: 8}).map((_,i)=>{ const a = (i/8)*Math.PI*2; const x=300+Math.cos(a)*120, y=180+Math.sin(a)*120; const kinds = ['person','project','person','org','domain','person','project','method']; const colors = {person:'#1c5fbf', project:'#d96b2c', org:'#2a8a5c', domain:'#b14fa6', method:'#7a6cf0'}; return ; })} {/* 2-hop ring */} {Array.from({length: 18}).map((_,i)=>{ const a = (i/18)*Math.PI*2 + 0.2; const x=300+Math.cos(a)*200, y=180+Math.sin(a)*200; return ; })} 2nd-degree neighbours your local ecosystem
); const AntiDup = () => (
{/* clusters showing duplication */} Membrane durability protocols ×3 teams Curriculum module: Hydrogen safety ×2 Pilot data sharing pattern {/* nodes inside clusters */} {[ [150,130],[180,160],[210,135], // cluster 1 [400,210],[440,220],[460,235], // cluster 2 [300,318],[330,322],[348,318] // cluster 3 ].map(([x,y],i)=>( ))} {/* dashed red edges between duplicates */}
Anti-dup mode
3 clusters detected · 8 stakeholders
Send introduction →
); window.NetworkTab = NetworkTab;