Health Gap Engine

A browser-native app that scores six HEDIS preventive care measures using AI models that run entirely on the member's device against synthetic patient data. No external API calls, no server, no health data in transit — the full inference pipeline runs locally.

Health Gap Engine


Summary

Health Gap Engine is a self-contained, browser-native web application that demonstrates what a payer-facing HEDIS quality measure scoring system looks like when the entire inference pipeline runs locally — no external API calls, no server-side computation, no protected health information in transit. The application scores six HEDIS measures — colorectal cancer screening, breast cancer screening, diabetes HbA1c control, blood pressure control, diabetes medication adherence, and depression screening — against synthetic patient data using six gradient-boosted classifiers trained on Synthea FHIR R4 data and exported to ONNX. All inference runs in the browser via ONNX Runtime Web. The architecture is designed to mirror what a production IBX SMART on FHIR integration would look like: the same FHIR R4 feature extraction logic, the same HEDIS eligibility rules, and the same explainability layer — with the OAuth flow and live API calls replaced by a local demo state for portfolio deployment.

Care Gap Intelligence Engine

Below is the live, in-browser ONNX inference demo.

Introduction

I built this project to demonstrate a specific capability to Independence Blue Cross: that a developer fluent in their interoperability stack can build a working, privacy-preserving member application on top of the APIs they already publish — in the same amount of time it takes most developers to scaffold a basic CRUD app.

IBX’s member portal already surfaces care gap reminders and screening alerts. What it does not expose is the underlying reasoning — which specific clinical data points are driving a gap flag, how close a member is to the threshold, or why one measure is flagged and another is not. Health Gap Engine addresses that directly. It pulls structured clinical data from the same FHIR R4 resource types that IBX’s Patient Access API exposes, runs six HEDIS quality measure classifiers locally in the browser, and produces a ranked, explainable gap dashboard with a direct action path to an in-network provider.

For portfolio deployment, I decoupled the application from IBX’s live OAuth infrastructure entirely. The production architecture — SMART on FHIR authentication, live FHIR resource fetching, Provider Directory API lookup — is preserved in the codebase as the intended integration target. What runs in the browser is a local demo state: the same inference pipeline, the same feature extraction logic, the same HEDIS eligibility rules, executing against synthetic patient data with no external dependencies.


Methods

The non-technical version

The app presents a synthetic patient — a 58-year-old woman with diabetes and hypertension who is overdue on several preventive screenings — and runs six small AI models against her health record, one for each preventive care measure. The models analyze things like her last lab results, past procedures, active diagnoses, and prescription history, then produce a risk score for each gap. Everything runs inside the browser. There are no server calls during inference, no health data in transit, and no login required to see the demo.

The architecture is designed to show exactly what the live version would look like: the same models, the same clinical logic, the same explainability layer — with the IBX login screen and live API calls swapped out for a local synthetic patient so the demo works anywhere, instantly, without credentials.

The technical version

Architecture. The application is a unified Single-Page Application deployed under a single route (/web-projects/Health_gap_engine/). All views — landing, loading, and dashboard — operate as states within a single SPA state machine rather than separate routes. This eliminates the external redirect dependency that SMART on FHIR OAuth requires: the callback URI, the authorization server redirect, and the token exchange flow are all bypassed in the demo state. The entire project directory is scoped and self-contained, with business logic, Svelte stores, and components isolated from the global repository to prevent namespace pollution and circular import dependencies.

Authentication bypass. In production, the app would execute a SMART on FHIR standalone launch against IBX’s authorization server at eapics.ibx.com using OAuth 2.0 with PKCE via fhirclient.js. For portfolio deployment, this flow is replaced by a local demo state that injects a synthetic patient record directly into the application stores, bypassing all external API calls. The synthetic patient — a 58-year-old female with Type 2 diabetes (E11.9), essential hypertension (I10), a colonoscopy six years prior, a mammogram three years prior, and four metformin fills in the last year — is constructed to produce a clinically realistic distribution of HIGH, MEDIUM, and LOW risk scores across the six measures.

Feature extraction. Each synthetic FHIR resource is parsed into a typed feature vector using the same extraction logic that would run against live IBX FHIR data. LOINC codes map observations to measures (HbA1c: 4548-4, systolic BP: 8480-6, PHQ-9: 44249-1); CPT codes identify procedures (colonoscopy: 45378, mammogram: 77067); ICD-10 prefixes match conditions (diabetes: E11, hypertension: I10); RxNorm display strings match medications. All imports are resolved against the scoped project path ($lib/data/js/Health_gap_engine/) using standardized absolute paths to satisfy Vite’s import analysis at build time. Feature vector lengths are fixed per measure: COL, HBD, CBP, and DSF each take 7 features; MAD takes 6; BCS takes 5.

Model training. Six GradientBoostingClassifier models were trained on 1,000 synthetic patients from the Synthea FHIR R4 dataset — publicly available, no real PHI. Each model is a binary classifier: gap closed (1) or gap open (0), with HEDIS eligibility filters applied before training. Models were exported to ONNX format via skl2onnx at opset 17, with output validated to match sklearn probabilities to four decimal places before export.

Browser inference. ONNX Runtime Web (ort.js) loads each model as a static asset, runs inference against a Float32Array feature tensor, and returns P(gap open) and P(gap closed). Sessions are cached after first load. A permutation-based attribution pass — zeroing each feature in turn and measuring the change in P(gap open) — produces the top-three contributing factors displayed in the detail modal. This is not exact SHAP, but it is directionally correct and runs in under 200ms per measure in the browser.

UI architecture. Navigation components and detail views were refactored from slide-in drawers into centered, reusable modals to integrate cleanly with the main portfolio layout. The style system uses scoped CSS variables throughout, preventing bleed into the global stylesheet. The gap dashboard, summary banner, and detail modal are all self-contained Svelte components with no external style dependencies.

Storage. The only write is a Firestore document keyed on a SHA-256 hash of the synthetic patient ID (browser-native crypto.subtle.digest, salted). The document contains the hashed key, a float map of gap scores, eligible measures, a timestamp, and an app version string. Firestore security rules enforce at the database level that no name, date of birth, address, phone, or email field can be written.

Stack. SvelteKit with the static adapter, deployed to Firebase Hosting. Svelte stores for all reactive state. Pure client-side SPA — SSR disabled, required because ONNX Runtime Web depends on browser APIs unavailable in Node. COOP and COEP headers set in firebase.json to enable SharedArrayBuffer for ONNX Runtime Web’s WASM backend.


© Dr. Balaji Ramanathan