VaxLink — Multi-Platform Support Roadmap¶
Current Architecture (the problem)¶
Two places in content.js are hardcoded per-platform:
| Location | What it does | Line |
|---|---|---|
isHandsFreeSupportedPage() |
Whitelist of allowed hostnames | 1023 |
autoFillTelus() |
Routes to Panorama fill OR generic fill | 3084 |
isPanoramaImmunizationPage() |
Detects Panorama-specific DOM | 2697 |
fillPanoramaImmunizationFields() |
Panorama-specific fill logic | 2720 |
Adding OSCAR/Wolf/PS Suite today = copy-pasting more if (isOSCAR) branches into those same functions. It will get messy fast.
Proposed Architecture: Platform Registry¶
No build tool needed — uses multiple content scripts loaded in order via manifest.
apps/extension/
├── manifest.json ← add new platform files to content_scripts
├── background.js
├── content.js ← refactored: reads from VAXLINK_PLATFORMS registry
├── popup.js / popup.html ← add platform indicator badge
├── platforms/
│ ├── registry.js ← defines VAXLINK_PLATFORMS = [] and helpers
│ ├── panorama.js ← extracted from content.js (no change in behavior)
│ ├── inputhealth.js ← extracted from content.js
│ ├── oscar.js ← new
│ ├── wolf.js ← new
│ └── psuite.js ← new
└── settings/
├── settings.html ← community config UI (add custom hostnames)
└── settings.js
Each platform file registers itself:
// platforms/oscar.js
VAXLINK_PLATFORMS.push({
id: 'oscar',
name: 'OSCAR EMR',
hostPatterns: ['oscar.', '.oscarhost.com', 'oscar-emr.'],
detect(host, doc) { /* optional DOM check */ return true; },
fill(data) { /* platform-specific fill */ }
});
content.js becomes platform-agnostic:
// isHandsFreeSupportedPage() becomes:
function isHandsFreeSupportedPage() {
const host = window.location.hostname.toLowerCase();
return VAXLINK_PLATFORMS.some(p => matchesHost(p, host));
}
// autoFillTelus() becomes:
function autoFillTelus(data) {
const host = window.location.hostname.toLowerCase();
const platform = VAXLINK_PLATFORMS.find(
p => matchesHost(p, host) && p.detect?.(host, document) !== false
);
return platform ? platform.fill(data) : genericFill(data);
}
Phase Breakdown¶
Phase 1 — Refactor (no behavior change)¶
- Create
platforms/registry.jswithVAXLINK_PLATFORMS = [] - Create
platforms/panorama.js— extract existing Panorama logic - Create
platforms/inputhealth.js— extract existing InputHealth logic - Update
manifest.jsonto load platform files beforecontent.js - Refactor
isHandsFreeSupportedPage()andautoFillTelus()to use registry - Zero behavior change — Panorama + InputHealth work identically
Phase 2 — New Platforms¶
platforms/oscar.js— OSCAR EMR (widely used in Ontario/BC/AB)platforms/wolf.js— Wolf EMRplatforms/psuite.js— PS Suite (Telus Health)- Requires inspecting each platform's immunization form field selectors
Phase 3 — Community Config System¶
settings.html/settings.js— settings page linked from popup- UI to add custom hostname patterns (stored in
chrome.storage) - UI to enable/disable built-in platforms
- Shows current active platform detection status
- Add a gear icon to popup linking to settings
Phase 4 — Popup Enhancement¶
- Show detected platform name in popup (e.g., "OSCAR EMR detected")
- Show "No supported platform on this page" when on an unsupported site
- Make "Auto-fill CHR" button label dynamic per platform
Platform Research Notes¶
| Platform | Common Hostnames | Notes |
|---|---|---|
| OSCAR EMR | oscar.*, *.oscarhost.com, *.oscar-emr.com |
Open-source Java; immunizations under /oscarRx/ or /appointment/ |
| Wolf EMR | *.wolfemr.com, wolfmedical.com |
Field names tend to be vaccine_, lot_, expiry_ patterns |
| PS Suite | *.ps-suite.com, pssuite.ca |
Telus Health product; likely similar to InputHealth |
TODO: Inspect actual running instances of OSCAR/Wolf/PS Suite to get accurate field selectors before implementing Phase 2.
Other Future Updates (backlog)¶
- Configurable platform hostnames — settings UI to add custom hostnames without code changes
- Audit log / fill history — log every auto-fill event to
chrome.storage, show in popup - Field selector warnings — surface warning in popup when expected fields aren't found
- Export (CSV/JSON) — export parsed barcode data or fill history for clinic reporting
- Unit tests — Vitest or
node:testfor GS1 parser and lot lookup logic - Batch barcode lookup (web app) — upload list of barcodes, get back resolved metadata CSV
- IndexedDB for bundle — replace
chrome.storage.localfor the large NVC bundle - Firefox support — MV3 now supported in Firefox, mostly compatible already
- Chrome Web Store publishing — polish for public distribution (clinics install without dev mode)