// H2Learn — supporting screens // Landing, Onboarding, Dashboard, Explorer, Admin, States (function() { const D = window.H2Data; const { useState } = React; // ============ LANDING ============ const LandingScreen = () => (
{/* nav */}
H
H2Learn Knowledge Match Maker
{/* hero */}
Open beta · NL hydrogen ecosystem

The hydrogen learning ecosystem,
finally connected.

Build a structured profile. Discover relevant peers, projects, methods, and shared challenges. Understand why every match matters.

location.hash='onboarding'}>Start profile location.hash='network'}>Explore demo
Built with HvA · TU Delft · TNO · 248 stakeholders · 134 explainable matches
{/* how it works */}
How it works

From questionnaire to graph in four moves.

{[ {n:'01', l:'Profile', d:'A guided questionnaire captures identity, expertise, projects, needs, offers, bottlenecks, uncertainties.'}, {n:'02', l:'Normalize', d:'Answers are normalized into structured entities and tagged via a shared taxonomy.'}, {n:'03', l:'Match', d:'Nine algorithm families compare profiles and projects, then create explainable relationship edges.'}, {n:'04', l:'Explore', d:'Browse the ecosystem as an atlas. Every match shows you the data behind it.'}, ].map(s => (
{s.n}
{s.l}

{s.d}

))}
{/* three pillars */}
{/* footer */}
); const PillarCard = ({eyebrow, title, body, cta, href, highlight}) => (
{eyebrow}

{title}

{body}

location.hash=href}>{cta}
); // mini graph for landing const LandingGraphic = () => (
{/* edges */} {/* nodes */} {[ {x:160, y:180, l:'SA', c:'var(--c-person)', r:22, focal: true}, {x:320, y:180, l:'LK', c:'var(--c-person)', r:18}, {x:200, y:240, l:'P', c:'var(--c-domain)', r:12}, {x:130, y:280, l:'BJ', c:'var(--c-person)', r:16}, {x:340, y:320, l:'HN', c:'var(--c-project)', r:24, hex:true, recommended: true}, {x:380, y:380, l:'IH', c:'var(--c-person)', r:18}, {x:260, y:380, l:'EL', c:'var(--c-project)', r:14, hex: true}, ].map((n,i) => ( {n.recommended && } {n.focal && } {n.hex ? : } 18 ? 12 : 10} fontWeight="600" fill={n.c}>{n.l} ))}
Atlas · live preview
★ Top match
Sara × HYDRO-NL
Complementarity · 88%
); function hexPoints(x, y, r) { return Array.from({length:6}).map((_,i) => { const a = -Math.PI/2 + i * Math.PI/3; return [x + r*Math.cos(a), y + r*Math.sin(a)].join(','); }).join(' '); } // ============ ONBOARDING ============ const ONBOARDING_STEPS = [ { id:'identity', l:'Identity', icon:'user', d:'Who you are' }, { id:'knowledge', l:'Knowledge', icon:'book', d:'Your expertise weighting' }, { id:'project', l:'Project', icon:'flask', d:'Active research/practice context' }, { id:'challenges', l:'Challenges', icon:'target', d:'Open problems you face' }, { id:'bottlenecks', l:'Bottlenecks', icon:'alert', d:'Where progress is blocked' }, { id:'uncertainties',l:'Uncertainties', icon:'compass', d:'What you don\'t know yet' }, { id:'evidence', l:'Evidence', icon:'sparkles', d:'Optional anchors · papers, datasets' }, { id:'review', l:'Review', icon:'check', d:'Submit & generate matches' }, ]; const OnboardingScreen = () => { const [step, setStep] = useState('knowledge'); const stepIdx = ONBOARDING_STEPS.findIndex(s => s.id === step); const progress = ((stepIdx) / (ONBOARDING_STEPS.length - 1)) * 100; return (
{/* left rail */}
Build your profile
Guided profiling
Step {stepIdx+1} of {ONBOARDING_STEPS.length} {Math.round(progress)}%
{ONBOARDING_STEPS.map((s, i) => ( ))}
Autosaved · 14 sec ago
{/* main */}
{step === 'knowledge' && setStep('project')} onBack={() => setStep('identity')}/>} {step === 'identity' && setStep('knowledge')}/>} {step === 'project' && setStep('challenges')} onBack={() => setStep('knowledge')}/>} {step === 'challenges' && setStep('bottlenecks')} onBack={() => setStep('project')}/>} {step === 'bottlenecks' && setStep('uncertainties')} onBack={() => setStep('challenges')}/>} {step === 'uncertainties' && setStep('evidence')} onBack={() => setStep('bottlenecks')}/>} {step === 'evidence' && setStep('review')} onBack={() => setStep('uncertainties')}/>} {step === 'review' && }
{/* right rail — signal preview */}
Signal this section produces
Expertise fingerprint
100-point allocation across subdomains
What it powers
Weighted similarity matches
Need ↔ Offer detection
Bridge-actor scoring
Your weight allocation creates the cosine vector used in similarity matching.
); }; const StepHead = ({n, total, title, desc, micro}) => (
Step {n} of {total} {micro && <>·{micro}}

{title}

{desc}

); const StepFooter = ({onBack, onNext, nextLabel='Continue', nextIcon='arrowRight'}) => (
{onBack ? Back : } {nextLabel}
); const IdentityStep = ({onNext}) => ( <>
{['Research','Education','Industry','Public sector','NGO'].map((s,i) => {s})}