Back to Projects

Stroke Localizer

Clinical education tool that maps stroke symptoms to infarcted brain regions and occluded arteries.

React 19TypeScriptVite 7Tailwind CSS v4React Three FiberThree.jsClaude APIVitest

Overview

A deep dive into the architecture, algorithms, and design decisions behind the Stroke Localizer — a clinical education tool that maps neurological symptoms to vascular territories using rule-based localization, 3D/2D visualization, and AI-powered text parsing.

Architecture Overview

Single-page application built with React 19, TypeScript, and Vite 7. The codebase follows a component-based architecture with centralized state management via useReducer + React Context.

Key architectural decisions: - TypeScript-first clinical data model — Every symptom, territory, and mapping rule is strongly typed, catching clinical logic errors at compile time - Two-context patternStrokeContext owns clinical state (symptoms, laterality, territories); UIContext owns interaction state (hover highlights, panel visibility) - Lazy-loaded 3D — Three.js and React Three Fiber are code-split into a separate 347 KB vendor chunk, loaded only when the 3D panel is visible - Zero-backend architecture — All localization logic runs client-side; AI features call provider APIs directly from the browser

Core Algorithm: Localization Engine

The heart of the app is a 3-phase confidence scoring pipeline that maps selected symptoms to vascular territories:

Phase 1 — Rule Matching Each of the 57 mapping rules links a symptom (optionally with laterality) to one or more vascular territories with a base confidence score. Rules are defined declaratively in a typed array, making them auditable and extensible.

Phase 2 — Score Adjustment Raw scores are refined with three modifiers: - Supporting bonus (+0.05) — When multiple symptoms independently support the same territory - Excluding penalty (−0.15) — When a symptom is atypical for a territory, reducing its confidence - Laterality bonus (+0.05) — When left/right laterality is consistent across symptoms pointing to the same territory

Phase 3 — Territory Deduplication After scoring, results are deduplicated by territory. If multiple rules point to the same territory, their confidence scores are merged (max score wins, supporting evidence accumulates). The final output is a sorted array of territories with confidence levels, contributing symptoms, and laterality data.

The engine covers 13 vascular territories including ACA, MCA (superior/inferior divisions), PCA, basilar, PICA, AICA, SCA, lacunar, and watershed zones.

Data Flow

The application follows a unidirectional data flow through five layers:

5 Input Modes → StrokeContext Reducer → Localization Engine → Visualization Layer → Bidirectional Hover

1. Input modes — Symptom checklist (60 symptoms, 7 categories), body diagram (motor/sensory quick-select), NIHSS calculator, free-text AI parsing, and voice input 2. Reducer dispatch — All inputs dispatch typed actions (ADD_SYMPTOM, SET_LATERALITY, REPLACE_NIHSS, etc.) to a single reducer 3. Engine execution — On every state change, the localization engine re-runs and produces an updated territory result set 4. Visualization — Results flow to the 3D brain, 2D SVG planes, Circle of Willis diagram, and the territory results panel 5. Bidirectional hover — Hovering a territory highlights its contributing symptoms; hovering a symptom highlights its matching territories. Managed via UIContext to avoid prop drilling

3D Visualization

Built with React Three Fiber and a dual-model rendering approach:

  • Procedural model — A simplified brain geometry generated from parametric curves, used for fast loading and territory overlay rendering
  • Anatomical GLTF model — A detailed brain mesh loaded from a compressed .glb file for anatomically accurate reference

Performance optimizations: - Three.js is lazy-loaded via React.lazy() and Suspense, keeping the initial bundle lean (347 KB vendor chunk loaded on demand) - Orbit controls allow full rotation, zoom, and pan - Territory meshes use dynamic opacity — matched territories glow at full opacity with color-coded confidence levels; unmatched territories fade to near-transparent - Hover interactions trigger smooth opacity transitions via useFrame animations

2D SVG System

Three anatomical planes plus the Circle of Willis, all rendered as inline SVG components:

Anatomical planes: - Axial (top-down cross-section) - Coronal (front-facing cross-section) - Sagittal (side-view cross-section)

Each plane is an SVG component with hemisphere-aware rendering — left and right territories are drawn on their correct anatomical side, with contralateral mapping for motor/sensory symptoms.

Circle of Willis diagram shows the arterial supply with occlusion markers that appear when a territory's feeding artery is implicated.

Interaction design: - Dynamic CSS styling applies color-coded fills based on confidence scores - Drop-shadow hover effects provide visual feedback - All SVG regions participate in the bidirectional hover system via shared UIContext state

AI Integration

Dual-provider architecture supporting both Claude and GPT-4o for clinical text parsing:

  • Client-side API calls — The browser sends the clinical description directly to the selected AI provider, with structured JSON extraction prompts
  • Structured output — The AI returns a JSON array of extracted symptoms with laterality, which is validated against the app's symptom enum before dispatching to the reducer
  • Provider fallback — Users can switch between Claude and OpenAI if one provider is unavailable

Voice input: - Local-first keyword matching — A dictionary of symptom keywords is matched against the speech transcript before invoking AI - AI fallback — If local matching produces low-confidence results, the transcript is sent to the AI parser for more nuanced extraction

NIHSS Calculator

Implements the NIH Stroke Scale, a 15-item standardized neurological assessment:

  • Each item (level of consciousness, gaze, visual fields, facial palsy, motor arm/leg, limb ataxia, sensory, language, dysarthria, extinction) is scored on its clinically defined scale
  • Score-to-symptom mapping — Each NIHSS score automatically maps to the corresponding symptom in the localization engine (e.g., "Motor Arm: 3" maps to "Upper extremity weakness")
  • Replace semantics — NIHSS dispatches use a REPLACE_NIHSS action that clears previous NIHSS-derived symptoms before adding new ones, preventing stale symptom accumulation when scores are adjusted
  • The total NIHSS score is displayed with clinical severity classification (0 = no stroke, 1–4 = minor, 5–15 = moderate, 16–20 = moderate-severe, 21–42 = severe)

Testing

243 unit tests (Vitest) + 9 end-to-end specs (Playwright) providing comprehensive coverage:

Unit tests cover: - Localization engine — symptom-to-territory mapping accuracy, confidence scoring, laterality handling, edge cases with conflicting symptoms - NIHSS calculator — score computation, symptom mapping, replace semantics - Voice processing — keyword matching, transcript normalization - React components — rendering, user interactions, state updates

E2E tests cover: - Full user workflows: select symptoms → verify territory results → check 3D/2D visualization - AI text parsing integration (with mocked API responses) - NIHSS workflow: score entry → symptom mapping → localization - Cross-browser compatibility (Chromium, Firefox, WebKit)

CI pipeline runs both test suites on every push via GitHub Actions.