A guided, contactless spirometry recording web application built for the electronRx technical challenge. Based on the non-contact spirometry approach described by Liu et al., which estimates respiratory function from camera-captured movement.
- Node.js ≥ 18
- A modern browser (Chrome 90+, Firefox 90+, Safari 15+)
cd spirometry-app
npm install
# Option A: run in demo mode (no Firebase needed)
npm run dev
# Option B: configure Firebase first (see below)
cp .env.example .env
# Edit .env with your Firebase values
npm run devOpen http://localhost:5173.
Create a Firebase project at console.firebase.google.com, then:
- Enable Cloud Firestore (start in test mode for development)
- Enable Firebase Storage (start in test mode for development)
- Copy your web app config values into
.env
VITE_FIREBASE_API_KEY=...
VITE_FIREBASE_AUTH_DOMAIN=...
VITE_FIREBASE_PROJECT_ID=...
VITE_FIREBASE_STORAGE_BUCKET=...
VITE_FIREBASE_MESSAGING_SENDER_ID=...
VITE_FIREBASE_APP_ID=...
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /recordings/{docId} {
allow read, write: if true; // ⚠ development only
}
}
}
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /recordings/{recordingId} {
allow read, write: if true; // ⚠ development only
}
}
}
If no Firebase credentials are configured, the app runs in demo mode:
- Video upload is simulated (2 s fake progress bar)
- Metadata is logged to the browser console instead of Firestore
- A warning banner is shown throughout the app
This allows the full UX flow to be tested without a Firebase project.
- Full 4-step user journey: ID entry → instructions → recording → completion
- Camera access with clear error handling (denied, not found, in use)
- MediaRecorder recording with live timer, progress bar, and auto-stop at 15 s
- Video review before submission
- Pre-submit quality checklist
- Upload to Firebase Storage with real-time progress
- Metadata saved to Firestore
- Demo mode (simulated upload + console logging) when Firebase is not configured
- Session persistence across page navigations (sessionStorage)
- Responsive layout
- No authentication: the app accepts any alphanumeric patient/clinic ID. See below.
- No video quality analysis: the recording is not checked for minimum duration, brightness, or motion quality.
- Safari WebM compatibility: Safari does not support
video/webm. The MediaRecorder falls back tovideo/mp4on Safari, but this is untested. - No offline support: upload will fail without an internet connection.
- No re-upload retry queue: if upload fails, the user must re-record (the blob is available for retry, but re-upload is not implemented).
Omitted intentionally given the prototype scope. In a production system I would:
- Add Firebase Authentication (email/password or SSO for clinic staff)
- Issue short-lived signed upload tokens server-side
- Tie Firestore documents to authenticated user UIDs
- Apply strict Firestore security rules rather than open test rules
Using the browser's native MediaRecorder API avoids a large dependency and gives direct control over codec selection and chunk collection. The trade-off is slightly more boilerplate, but it's transparent and auditable.
The spec explicitly permits this. A production version would use a backend to issue short-lived Firebase Auth tokens and validate IDs against a patient registry.
Simple and appropriate for a prototype. Cleared on tab close. No sensitive data is persisted beyond the session.
- Re-upload without re-recording: if upload fails, retry from the existing blob
- Recording quality feedback: detect if the video is too dark, or if the exhalation was too short, and prompt the user
- Accessibility: keyboard navigation, screen-reader labels, contrast audit
- Tests: unit tests for
useMediaRecorder,session.js, and the Firebase service layer - Mobile layout: the current layout works on mobile but hasn't been optimised for portrait camera orientation
- Authentication and RBAC: clinic staff accounts, patient identity verification
- Data governance: GDPR / HIPAA compliant storage, data retention policies, audit logs
- Security rules: strict Firestore and Storage rules, backend token issuance
- Video integrity: checksum verification after upload, immutable storage
- Clinical validation: validation study comparing camera-derived metrics against spirometer ground truth
- Consent: explicit informed consent flow before recording
- Accessibility and localisation: WCAG 2.1 AA, multi-language support