Congenital Heart Disease Pattern Recognition for Medical Students
A cognitive learning tool that trains second-year medical students to recognize the 12 most important congenital heart diseases using progressive disclosure, spaced repetition, and immediate contrastive feedback—the way they'll encounter them on Step 1.
👉 Launch the Game — Test your CHD pattern recognition skills!
No installation required. Works in any modern browser.
Medical education drowns students in detail before they develop schemas. Guess the CHD inverts that: pattern first, detail later. The five-rung ladder mirrors clinical reality—you never get all the data at once. You build a hypothesis with fragments, then refine it.
- Desirable difficulty — R1 forces schema activation before confirmation
- Contrastive learning — Nearest distractor = the distinction experts make effortlessly
- Retrieval practice — Active recall > passive review
- Spacing — Weak items resurface = durable learning
This isn't a quiz. It's deliberate practice for pattern recognition.
Each case presents clues progressively:
- R1: Whisper (≤12 words) — The tiniest hint
- R2: Pathophys — One vital physiologic cue
- R3: Image — CXR crop with a classic sign
- R4: Audio — ≤2s heart sound snippet
- R5: Confirm — Full CXR or association pearl
Students can submit their diagnosis at any rung. Earlier recognition = more points.
- R1 answer: 100 pts
- R2 answer: 80 pts
- R3 answer: 60 pts
- R4 answer: 40 pts
- R5 answer: 20 pts
- Rationale bonus: +10 pts
Partial credit for correct category, wrong diagnosis. No penalties—exploration is encouraged.
Missed cases resurface after 1, 3, then 7 new cases (simplified Leitner algorithm). Research shows spacing > massing for long-term retention.
Every answer includes:
- Whether it's correct
- Full explanation with physiology
- Nearest distractor contrast ("Why NOT X?")
- Clinical pearl (association/embryology hook)
- Atrial Septal Defect (ASD)
- Ventricular Septal Defect (VSD)
- Patent Ductus Arteriosus (PDA)
- Coarctation of the Aorta (CoA)
- Pulmonic Stenosis (PS)
- Tetralogy of Fallot (TOF)
- d-Transposition of Great Arteries (TGA)
- Truncus Arteriosus
- Total Anomalous Pulmonary Venous Return (TAPVR)
- AV Septal Defect (AVSD)
- Ebstein Anomaly
- Hypoplastic Left Heart Syndrome (HLHS)
Why These Choices?
- React + Vite + TypeScript — Component model maps 1:1 to rung ladder; fast refresh for rapid iteration; type safety prevents clinical content errors
- No backend (initially) — Local storage = zero latency, works offline, no auth complexity
- Static deployment — Vercel/GitHub Pages = free, instant, global CDN
- Node.js 18+ and npm
# Clone the repository
git clone https://github.com/stevetodman/guessthechd.git
cd guessthechd
# Install dependencies
npm install
# Start development server
npm run devVisit http://localhost:5173 to see the app.
npm run buildThe optimized static site will be in the dist/ directory.
npm run previewguessthechd/
├── public/
│ ├── cases/ # Media assets (CXR images, audio)
│ │ ├── asd/
│ │ ├── vsd/
│ │ └── ...
│ └── heart.svg # Favicon
├── src/
│ ├── components/
│ │ ├── GameBoard.tsx # Main game orchestrator
│ │ ├── RungDisplay.tsx # Renders R1-R5
│ │ ├── AnswerPanel.tsx # Answer submission
│ │ ├── ScoreCard.tsx # Progress tracking
│ │ └── LandingPage.tsx # Intro + start
│ ├── data/
│ │ └── cases.ts # All 12 CHD cases (single source of truth)
│ ├── hooks/
│ │ └── useGameState.ts # Game state management
│ ├── utils/
│ │ ├── scoring.ts # Points calculation
│ │ └── spacedRepetition.ts # Leitner algorithm
│ ├── types.ts # TypeScript definitions
│ ├── App.tsx # Root component
│ ├── App.css # App-specific styles
│ ├── index.css # Global styles
│ └── main.tsx # Entry point
├── index.html
├── vite.config.ts
├── tsconfig.json
└── package.json
- Push your code to GitHub
- Visit vercel.com
- Click "New Project" → Import your repo
- Vercel auto-detects Vite → Click "Deploy"
- Done! Your app is live at
https://your-project.vercel.app
-
Install the
gh-pagespackage:npm install --save-dev gh-pages
-
Update
vite.config.tsto set the base path:export default defineConfig({ plugins: [react()], base: '/guessthechd/', // Match your repo name })
-
Add deploy scripts to
package.json:{ "scripts": { "predeploy": "npm run build", "deploy": "gh-pages -d dist" } } -
Deploy:
npm run deploy
-
Enable GitHub Pages in your repo settings (Settings → Pages → Source:
gh-pagesbranch)
Your app will be live at https://yourusername.github.io/guessthechd/
- Push your code to GitHub
- Visit netlify.com
- Click "New site from Git" → Choose your repo
- Build settings:
- Build command:
npm run build - Publish directory:
dist
- Build command:
- Click "Deploy site"
Clinical images and audio files are stored in public/cases/[case-id]/.
r3-crop.jpg— CXR crop showing classic signr4-audio.mp3— Heart sound (≤2 seconds)r5-full.jpg— Full CXR or confirmatory image
See public/cases/README.md for detailed specifications.
Note: The app works without media (shows placeholders). Focus on content first, add media later.
-
Update
src/data/cases.ts:{ id: 'new-case', name: 'New Case Name', category: 'acyanotic-shunt', // or other category recognition: '...', hook: '...', nearestDistractor: { name: '...', whyNot: '...' }, rungs: [ { type: 'whisper', content: '...' }, { type: 'pathophys', content: '...' }, { type: 'image', content: '...', media: { url: '/cases/new-case/r3-crop.jpg' } }, { type: 'audio', content: '...', media: { url: '/cases/new-case/r4-audio.mp3' } }, { type: 'confirmatory', content: '...' }, ], reveal: '...', }
-
Add media files to
public/cases/new-case/ -
Update type map in
src/types.tsif needed (for answer matching)
Edit constants in src/types.ts:
export const RUNG_POINTS = [100, 80, 60, 40, 20]; // Adjust as needed
export const RATIONALE_BONUS = 10;Edit intervals in src/utils/spacedRepetition.ts:
const REVIEW_INTERVALS = [1, 3, 7]; // Cases until reviewReal clinical reasoning starts with minimal data. The rung system forces students to:
- Activate their schema (R1)
- Refine with physiology (R2)
- Confirm with imaging/audio (R3-R4)
- Lock in with associations (R5)
This mirrors Step 1 vignettes and real patient encounters.
Experts distinguish TOF from isolated PS instantly. Novices confuse them. The "nearest distractor" feedback builds those expert contrasts explicitly.
Cramming works for tests, not retention. Spacing + retrieval practice = durable knowledge.
- Analytics dashboard (track weak categories)
- Custom case sets (user-created content)
- Timed mode (Step 1 pressure simulation)
- Mobile app (React Native)
- Multiplayer/competitive mode
- Integration with Anki (export missed cases)
Contributions welcome! Please:
- Fork the repo
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE file for details.
Clinical content adapted from standard Step 1 resources. This tool is for educational purposes only and is not a substitute for comprehensive medical training.
Questions? Open an issue on GitHub or reach out to the maintainers.
Remember: This isn't about memorizing lists. It's about building clinical intuition—one case, one pattern, one "aha!" moment at a time.