FHIR + CDS Hooks + Gemini: a Risk Score a Clinician Will Actually Read
Risk scores die when they're black boxes. MeldRx integration via FHIR/CDS Hooks pulls patient data; Gemini Flash returns structured JSON with explanations, confidence, and recommended actions; the UI hands clinicians a downloadable PDF report.
Risk-prediction widgets that bolt onto an EHR get ignored when they don't explain themselves. The MeldRx Hackathon was an excuse to design the explanation surface first and let the model fit into it.

Why I built it
Before this hackathon I had never built a healthcare app, and I had not heard of CDS Hooks or FHIR. I wanted a forced excuse to learn that side of the industry on a real integration target rather than reading specs in the abstract. The other motivation was simpler: clinicians are under time pressure, and a tool that surfaces patient history faster, with its reasoning visible, is something I would want next to me if I were the one making the call.
What it does
Inside the MeldRx EHR view, a button on the patient card opens the assistant. The handoff runs through a SMART-style consent flow so the user explicitly authorizes data access before anything is read. Once inside, the app pulls the patient's Condition and Observation resources over FHIR and sends them to Gemini Flash for analysis.
The output that comes back is opinionated: a risk score with a transparent explanation, recommended actions, preventive measures, and a short summary written for a clinician who has thirty seconds. The model also self-reports an accuracy estimate with the reasoning behind that estimate, and the whole analysis can be exported as a PDF that lives in the chart.

Structured output is non-negotiable
Gemini Flash is asked for strict JSON with fields the UI relies on: risk_score, confidence, drivers, suggested_actions. Retry logic on malformed responses guarantees the contract. If the model returns prose, I re-ask. The downstream UI never has to defensive-parse.
Active vs resolved is the visualization that earned its space
Most condition lists treat everything as current. A clinician's brain doesn't. The dashboard splits active and resolved conditions visually, surfaces the most common diagnoses across the panel, and exports the consolidated summary as a downloadable PDF, the artifact a clinician actually saves to the chart.

How I built it
Next.js with a mix of JavaScript and TypeScript on top, CDS Hooks and FHIR as the integration contract for pulling patient data out of MeldRx, React Redux for state, Recharts for the visualizations, Tailwind plus DaisyUI for styling, and @react-pdf/renderer for the chart-ready export. Gemini Flash sits behind an axios call wrapped in retry logic. Hosted on Vercel.
- Gemini Flash was picked specifically for latency. Healthcare workflows do not tolerate a 12-second wait on a card click.
- CDS Hooks is the contract for when the app is allowed to surface, FHIR is the contract for what it reads. Both are non-optional for being taken seriously inside an EHR.
- Redux is heavier than the app strictly needs, but it makes the consent flow + analysis state easy to reason about across the cards.
What was hard
Prompt engineering the output until it landed in the exact JSON shape the UI expected took the most time. Beyond the prompt, the model occasionally returned malformed JSON during testing. The fix was a backoff retry: wait 500 ms on failure to avoid hammering the model, then try again up to 10 times. Since adding it I have not seen a single failure reach the UI.
The other hard part was just the learning curve. CDS Hooks, FHIR resource shapes, the SMART auth handoff, none of that was on my map before this hackathon. Most of the first day went into reading specs and the MeldRx sandbox docs before any code that mattered got written.
What I learned
- In a clinical UI, the explanation is the feature. The score is the side effect.
- Strict JSON contracts plus retry beat trying to clean up prose output every time.
- FHIR is verbose but predictable. Once you accept the resource model, everything maps cleanly.
What's next
Accuracy. The highest self-reported number I have seen is 85%, and I want that higher by extracting more of the relevant patient signal and pushing further on prompt structure. After that, the bigger idea is turning the assistant into a queuing layer: have the model output a priority that gets posted back to the MeldRx card view so triage isn't strictly first-come-first-served. Patient text notifications about appointment progress fit naturally into the same loop.
Last item on the roadmap is moving off a hosted frontier model. Gemini was the right call for shipping in 48 hours, but a production version of this should run on a small language model or a fine-tuned in-house model, both for data residency and for predictable behavior on the JSON contract.

Helping Condo Owners Argue with 200-Page PDFs
A special assessment notice lands and a condo owner has 30 days to decide whether to fight it. The PDF is 200 pages of accounting and legalese. CondoShield reads it, surfaces the levers, and drafts the dispute letter, in English or French.

Letting Gemini Write SQL Against BigQuery, So Fans Don't Have To
Personalized baseball coverage that actually personalizes: follow your players, pick your schedule, and an LLM-translated SQL layer lets the AI generate stats and visualizations against fresh MLB data without code changes.
