Rebuild GaugeGap for strangers and client conversion#91
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the GaugeGap landing page and arcade to optimize the user journey for first-time visitors and potential clients. Key changes include introducing intent-based audience pathways, lazy-loading individual experiments to improve performance, adding topic filters, and detailing a strategic product funnel in a new documentation file. The review feedback focuses on improving code maintainability and robustness by passing the lab-opening handler as a prop to eliminate duplicate logic, adding defensive checks for the daily lab state, and correcting invalid HTML nesting of paragraph tags inside buttons.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| export function VisitorRoutes({ onResearch }) { | ||
| function chooseRoute(route) { | ||
| track('gaugegap_pathway_selected', { pathway: route.id }); | ||
| if (route.lab) openLab(route.lab); | ||
| if (route.route === 'research') onResearch?.(); | ||
| if (route.target) document.getElementById(route.target)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); | ||
| } |
There was a problem hiding this comment.
Accept onOpenLab as a prop and use it instead of the duplicated module-level openLab helper. This allows us to completely remove the duplicated openLab function from this file, improving maintainability.
| export function VisitorRoutes({ onResearch }) { | |
| function chooseRoute(route) { | |
| track('gaugegap_pathway_selected', { pathway: route.id }); | |
| if (route.lab) openLab(route.lab); | |
| if (route.route === 'research') onResearch?.(); | |
| if (route.target) document.getElementById(route.target)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); | |
| } | |
| export function VisitorRoutes({ onResearch, onOpenLab }) { | |
| function chooseRoute(route) { | |
| track('gaugegap_pathway_selected', { pathway: route.id }); | |
| if (route.lab) onOpenLab?.(route.lab); | |
| if (route.route === 'research') onResearch?.(); | |
| if (route.target) document.getElementById(route.target)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); | |
| } |
| <button type="button" className="gg-scroll-cue" onClick={() => scrollTo('gg-start-heading')} aria-label="Choose a starting path"><span>Choose your path</span><ChevronDown size={17} /></button> | ||
| </section> | ||
|
|
||
| <VisitorRoutes onResearch={openResearch} /> |
There was a problem hiding this comment.
| </div> | ||
|
|
||
| <ArcadeProgress progress={progress} level={level} levelProgress={levelProgress} achievements={achievements} dailyLab={dailyLab} onOpenDaily={() => selectExperiment(dailyLab.id)} /> | ||
| <ArcadeProgress progress={progress} level={level} levelProgress={levelProgress} achievements={achievements} dailyLab={dailyLab} onOpenDaily={() => { setFilter('all'); selectExperiment(dailyLab.id); }} /> |
There was a problem hiding this comment.
Enforce defensive programming by adding a null/undefined check for dailyLab before accessing its id property in the onOpenDaily callback to prevent potential runtime crashes if dailyLab is not available.
| <ArcadeProgress progress={progress} level={level} levelProgress={levelProgress} achievements={achievements} dailyLab={dailyLab} onOpenDaily={() => { setFilter('all'); selectExperiment(dailyLab.id); }} /> | |
| <ArcadeProgress progress={progress} level={level} levelProgress={levelProgress} achievements={achievements} dailyLab={dailyLab} onOpenDaily={() => { if (dailyLab?.id) { setFilter('all'); selectExperiment(dailyLab.id); } }} /> |
| <span className="gg-route-icon"><Icon size={22} /></span> | ||
| <small>{route.eyebrow}</small> | ||
| <strong>{route.title}</strong> | ||
| <p>{route.text}</p> |
There was a problem hiding this comment.
Using a <p> element inside a <button> is invalid HTML5, as <button> elements should only contain phrasing content. Consider changing <p> to a <span> with a class name (e.g., className="gg-route-desc") and updating the corresponding CSS selector in audience-pathways.css to use display: block.
| <p>{route.text}</p> | |
| <span className="gg-route-desc">{route.text}</span> |
| .gg-route-card p { | ||
| margin: 11px 0 18px; | ||
| color: var(--bsn-text-secondary); | ||
| font-size: 0.88rem; | ||
| line-height: 1.55; | ||
| } |
There was a problem hiding this comment.
Update the selector from .gg-route-card p to .gg-route-card .gg-route-desc and add display: block; to ensure valid HTML semantics while maintaining the block-level layout.
.gg-route-card .gg-route-desc {
display: block;
margin: 11px 0 18px;
color: var(--bsn-text-secondary);
font-size: 0.88rem;
line-height: 1.55;
}
Why
The public experience had strong experiments but weak product clarity. A stranger could play, yet still not know what GaugeGap is, how BrainSNN relates to it, where to start, or what an organization can buy.
What this changes
Stranger-first journey
Client conversion
Trust and product clarity
Measurement
Documentation
Validation requested