ICNA Relief Health Fair Portal
ICNA Relief · Full-Stack Engineer · Mar 2026 – Present
A production Laravel application that lets rotating volunteers register patients and record clinical screenings at seven stations, writing everything to Salesforce through a resilient Apex REST integration.
0
PHI records stored locally
7
clinical screening stations
OAuth 2.0
resilient Salesforce integration
Problem
ICNA Relief runs community health fairs where volunteers need to move fast: register attendees, capture vitals, and log screenings — blood pressure, glucose, anemia, lipid panel, HbA1c, and more — on shared tablets, often with spotty Wi-Fi and a different volunteer at the station every hour.
All of that data has to land in Salesforce reliably, because Salesforce is the organization's system of record. Asking rotating volunteers to work directly in Salesforce was a non-starter, so this portal is the thin, purpose-built layer in front of it.
Architecture
Shared tablets
OTP auth · localStorage ↔ session sync
Laravel 12 portal
session state only — no patient data stored
Salesforce Apex REST
single source of truth for all clinical data
Technical Decisions
Store no patient data, anywhere
The portal deliberately keeps no local database of clients or health results — Laravel holds only session state (selected fair, cached search results, auth). For a healthcare-adjacent system this is the strongest possible privacy posture: there is no second copy of PHI to secure, audit, or migrate, and Salesforce remains the unambiguous system of record.
A real integration layer, not an HTTP wrapper
The Salesforce client implements OAuth 2.0 client credentials with cached tokens and TTL management, automatic refresh on 401s, configurable retries with backoff for transient failures, and structured error parsing. Field conditions — flaky Wi-Fi, long days, token expiry mid-event — were the design assumption, not an edge case.
Validation mirroring Salesforce schemas
Form validation reproduces Salesforce field rules client-side — height as feet.inches (5.08 for 5'8"), age and weight bounds, picklist values — so bad data is rejected at the tablet instead of bouncing off the API mid-rush. The ClientStationData layer also normalizes Salesforce's inconsistent field naming into stable form defaults.
Auth shaped around how volunteers work
Email OTP restricted to the org domain, rate limiting on OTP endpoints, optional HTTP Basic Auth for shared station devices with timing-safe comparison, and a feature flag for throwaway test deploys that displays a visible 'Auth disabled' badge. Session regeneration after OTP verification. Practical security for shared devices, with tests covering the auth flag, OTP bypass, and Basic Auth behavior.
Challenges
Shared-tablet handoff
Volunteers hand tablets to each other constantly, and losing the selected health fair on every handoff meant re-navigation at the worst moment. The fix: persist event selection in localStorage and sync it back into the Laravel session on page load, so context survives across volunteers, page reloads, and session churn.
Instant feedback without a second round-trip
After a successful Salesforce save, volunteers need to see the new reading immediately — but re-fetching from Salesforce adds seconds when people are queued at a station. A SyncsClientSession concern merges the just-saved values into session state, so the UI reflects new data instantly while Salesforce remains the source of truth.
Schema bridging across naming conventions
The same blood pressure value might arrive as Systolic_Blood_Pressure__c, bloodPressureSystolic, or nested under results.bloodPressure depending on the endpoint. Normalizing this mess into consistent form defaults is unglamorous work, but it's exactly the work that makes an enterprise integration hold up in production.
Production deployment for field operations
Multi-stage Docker builds (PHP 8.3-FPM, Nginx), images pushed to GHCR, GitHub Actions CI/CD with SSH deploys of immutable SHA-tagged images, Traefik with Let's Encrypt for HTTPS, migrations on container start, health checks at /up. A health fair can't wait on a broken deploy — the pipeline had to be boring and repeatable.