Most medical quiz apps score you as right or wrong. That throws away the part that matters. In clinical reasoning, mistaking cholecystitis for appendicitis and mistaking it for a myocardial infarction are not the same mistake. One is a near miss inside the acute abdomen. The other is a different organ system.
So when we built NEXO, a daily diagnosis game for physicians and medical students, we made the scoring reflect that.
The idea
ICD-10 is a tree. A code like I21.0 sits inside category I21, inside group I20-I25, inside the chapter for diseases of the circulatory system. That hierarchy is already a distance metric. We just had to use it.
When a player submits a guess, we compare the guessed code against the answer and return the deepest node they share:
exact code I21.0 vs I21.0
same category I21.9 vs I21.0
same group I20 vs I21.0
same chapter I50 vs I21.0
different chapter J18 vs I21.0
Five levels instead of two. A player who lands on "same chapter" learns they were reasoning in the right system and missed the specific entity. A player who lands on "different chapter" learns something else entirely. Both are wrong answers, and they are not worth the same.
Keeping the answer secret
The daily case is the same for every player worldwide, and the answer has to stay hidden until the day rolls over. The comparison runs server side against the stored code. The client never receives the answer, only the level. That kept the API small: send a code, receive an enum.
The harder problem: cases that hold up
Generating a plausible clinical case with an LLM takes seconds. Generating one a physician will not tear apart is a different problem. A clue that sounds right but does not belong to the diagnosis is worse than no clue at all.
We built NEXO Core for that. Every disease, syndrome, exam, clinical finding and ICD-10 code is a node. Edges connect what clinical practice treats as neighbors: pneumonia connects to its etiological agent, its radiological pattern, its differentials. The graph currently holds around 11,500 concepts and 26,000 edges, drawn from 27 reference textbooks.
Every generated case crosses that graph before approval. Each clue has to appear among the neighboring concepts of the proposed diagnosis. A clue that does not, fails. It is a structural check, not a human reading it over and nodding.
Stack
- React Native with Expo for the app
- Supabase for Postgres, auth, storage and edge functions
- Next.js on Vercel for the marketing site and the case management backoffice
- RevenueCat and StoreKit 2 for subscriptions
- Sentry for crash reporting
649 cases across 25 specialties, in six languages.
What I would do differently
Start with the graph, not the cases. We wrote a few hundred cases before the graph existed and had to re-audit all of them against it afterwards. That audit found problems a read-through had missed.
NEXO is live on iOS and the daily case is free forever, with no ads. The site is at nexo.wiki.br and the app is on the App Store.
Happy to answer questions about the graph or the scoring.
Top comments (0)