08 / Healthcare
FHIR R4 patient explorer
Synthetic data · HAPI sandbox
A read-only window onto a public FHIR R4 test server seeded with synthetic records. No real patient data is involved, nothing is persisted, and nothing beyond request metadata is logged.
Patients
Run a search to list matching patients.
Patient summary
Select a patient to load the summary: demographics, counts, active conditions, and recent vital signs.
- Conditions
- 0
- Encounters
- 0
- Observations
- 0
Active conditions
Vitals
| Date | Vital sign | Value |
|---|
No vital signs recorded for this patient.
$ waiting for the first search
The DTO the function returned
How This Demo Is Built
The same shape as the rest of the site: static HTML in front, a small C# function behind CloudFront, and the contract written before the code.
- Data source
- The public HAPI FHIR R4 test server, which holds only synthetic records and is wiped and repopulated from time to time, so nothing here depends on a particular patient id. The base URL is configuration; the SMART Health IT sandbox is the one-variable fallback when HAPI is down. The function reads the server's
CapabilityStatementonce per instance to confirm the resources and search parameters the explorer needs are supported. - API
- Five read-only endpoints under
/api/fhir, specified in the same OpenAPI document as the Experience API: patient search, patient summary, the raw bundle behind a summary, the capability subset, and a health check. C# on .NET 10, run on AWS Lambda (arm64) behind this distribution. The browser never talks to the sandbox; the function is the boundary, and only the raw-bundle endpoint passes FHIR JSON through. - FHIR handling
- The Firely SDK parses every resource into typed objects. A summary reads the
Patient, then runs four bounded searches at once: conditions, vital-sign observations, and_summary=countfor encounters and observations, followinglink[rel=next]up to five pages each. Mappers read only the fields US Core makes mandatory or must-support, split conditions onclinicalStatus, prefer SNOMED CT or ICD-10-CM codings, and pick vital signs by LOINC code, with blood pressure carrying its systolic and diastolic components. - Resilience
- The public sandbox is sometimes slow. Every upstream call has a six-second attempt timeout, two retries with exponential backoff and jitter, a circuit breaker, and a 22-second total budget under CloudFront's 30-second origin limit. A timeout or server error comes back as an RFC 9457 problem (
504or502) that the page turns into a plain message, never a blank screen. - Caching and limits
- Responses carry an ETag and
Cache-Control, and CloudFront caches on the path plus the three search parameters, so a repeated request is answered at the edge; the panel above shows theX-Cacheheader and labels a hit's timings as those of the original request. A per-address budget in the function's memory answers429past sixty requests in ten minutes. No cookies, no analytics, no PHI, nothing stored. - Front end
- This page is plain HTML with one deferred script of its own,
fhir.js, and no dependencies, under the site's Content Security Policy (no inline script or style). The avatar colours, the pills, and the log block are classes in the shared stylesheet; the layout stacks on a phone and splits on a desktop.