Built for FrostByte Hackathon 2026
Sarah is 34. She goes for her usual Saturday morning run in Central Park. Two miles in, she collapses.
A bystander calls 911. The paramedic arrives in four minutes. Sarah is unconscious. Her iPhone is locked β Face ID won't work on an unconscious face. Her emergency contact isn't picking up.
The paramedic needs to know two things right now:
- Is she allergic to anything?
- What medications is she on?
She has no way to know that Sarah has a severe sulfa drug allergy and takes warfarin β a blood thinner that makes certain emergency interventions life-threatening. She makes a judgement call based on zero information.
She gets lucky. Sarah survives.
Millions of people aren't that lucky.
The instinctive answer is "just put it in your phone's Medical ID." But Medical ID only works if:
- The paramedic knows to look for it
- The right information was entered and kept up to date
- The doctor treating you is in the same country, speaks the same language, and has time to scroll through a phone
The deeper answer is that the medical records system was never designed for emergencies. It was designed for scheduled appointments between a patient who is awake, coherent, and cooperative β and a doctor who has time to look things up.
The moment that design assumption breaks down β car accident, stroke, allergic reaction, cardiac arrest β the entire system fails simultaneously.
Consider what happens when that emergency occurs:
- Your records are locked inside hospital portals that don't talk to each other
- The ER doctor treating you has never seen you before and has no access to your history
- If you're travelling internationally, the language barrier makes everything worse
- Every minute spent tracking down your records is a minute not spent treating you
This is not a rare edge case. It is the default state of emergency medicine. Doctors make critical treatment decisions with incomplete information every single day β not because the information doesn't exist, but because there is no reliable way to get it to them in time.
Here is what we noticed that others missed:
The problem is not storing medical records. That has been solved. The problem is delivering the right records to the right doctor in the right language in the first 60 seconds of an emergency β without requiring the patient to do anything.
Every existing solution fails this test:
| Solution | Where It Breaks Down |
|---|---|
| Hospital patient portals | Doctors at a different hospital β or a different country β have no access |
| Health apps (Apple Health, etc.) | Require the patient to unlock their phone and navigate to the right screen |
| Paper records / printouts | Left at home, lost, or illegible under stress |
| USB drives | Require a computer, a compatible port, and time nobody has |
| Patient-provided summaries | Patients control what they share β no chain of custody, no way to verify |
| Doctor-to-doctor fax / referral | Requires advance planning, takes hours, completely useless in an emergency |
None of these work when the patient is unconscious. None of them work across language barriers. And critically β none of them can prove that the document the doctor sees is the same document that was originally created, not a selectively edited screenshot.
MedVault solves all three.
MedVault is a zero-knowledge, end-to-end encrypted health record platform with one core design principle:
Medical information should reach the doctor who needs it, in the language they speak, in under 10 seconds β regardless of whether the patient can help.
Here is how it works:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PATIENT (at home, healthy, five minutes of setup) β
β β
β Uploads lab results, prescriptions, vaccine cards β
β β β
β AES-256-GCM encryption happens in the browser β
β Server receives only ciphertext β we cannot read your files β
β β β
β Prints a wallet card: name + QR code. Nothing else. β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
[ EMERGENCY ]
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PARAMEDIC (no account, no app, just a phone camera) β
β β
β Scans the QR code on the wallet card β
β β β
β Browser decrypts the original documents β not summaries, β
β not screenshots, the actual original encrypted files β
β β β
β AI generates a clinical summary in the doctor's language β
β Blood type Β· Allergies Β· Medications Β· Conditions β
β β β
β Access expires automatically. Every scan permanently logged. β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Scan. Eight seconds. In her language:
PATIENT: Sarah Chen, 34, Female
BLOOD TYPE: A+
β CRITICAL ALERTS
β’ Severe sulfa drug allergy β do NOT administer sulfonamides
β’ Currently on warfarin β elevated bleeding risk, check INR before procedures
ACTIVE CONDITIONS
β’ Atrial fibrillation (diagnosed 2023)
CURRENT MEDICATIONS
β’ Warfarin 5mg daily Β· Metoprolol 25mg twice daily
EMERGENCY CONTACT
β’ James Chen (Husband) Β· +1 (212) 555-0147
No app. No account. No phone unlock. No language barrier. No guesswork.
Every document is encrypted in your browser using AES-256-GCM before it ever touches our servers. We store only encrypted ciphertext. This is not a privacy policy β it is a cryptographic guarantee. Even a complete breach of our servers exposes nothing readable.
Generate a time-limited QR code. Any doctor scans it with any phone camera β no app download, no account creation, no waiting room paperwork. Configurable expiry: 15 minutes, 30 minutes, or 1 hour. Access ends automatically.
Gemini AI reads your decrypted documents and generates a structured clinical summary in the doctor's chosen language β 15 languages, including Yoruba, Hausa, and Igbo alongside English, French, Spanish, Arabic, and 8 others. The language barrier between patient and doctor disappears.
A credit-card sized card (ISO 85.6Γ54mm) you keep in your wallet behind your driver's licence. Front: your name and a QR code. After scanning: blood type and allergies β the two pieces of information that can cause immediate death if unknown. Exportable as a print-ready PNG. No PIN, no barrier β modelled on the MedicAlert bracelet. Works when you are unconscious.
AI extracts numeric biomarkers from every lab result you upload β HbA1c, cholesterol, haemoglobin, kidney function, thyroid levels, and 20+ others β and plots them over time. Watch your health trajectory across months and years. Results are cached so Gemini analyses each document exactly once.
Every time a doctor scans your QR, it is logged permanently β timestamp, language used, whether it was a first or repeated access. You can see exactly who has viewed your records and when. This is the transparency that paper records, USB drives, and most health apps have never provided.
Your encryption key is derived from your password using PBKDF2-SHA256 (100,000 iterations) and exists only in your browser's memory for the duration of your session. It is never transmitted to our servers. A complete compromise of our infrastructure exposes nothing but encrypted bytes.
When a doctor uses the emergency QR, their browser decrypts the original file β the exact bytes you uploaded. You had no opportunity to modify it after upload. The document the doctor sees is cryptographically identical to the original. This is the chain of custody that no other patient-facing health tool provides.
- Create your vault β sign up, complete your medical profile (blood type, allergies, medications, conditions, emergency contacts)
- Upload your documents β lab results, prescriptions, vaccine records, imaging reports β encrypted automatically in your browser
- Print your wallet card β one click from the Dashboard generates a print-ready PNG with your name and QR code
- You're done β carry the card. Update your documents when you get new results.
- Paramedic or ER doctor finds the card in your wallet
- Scans the QR with any phone camera β opens instantly in a browser, no app required
- Selects their language from 15 options
- Clicks Generate Summary β AI produces a structured clinical summary in under 10 seconds
- For full documents β generate a time-limited QR from the Emergency Share screen; doctor decrypts your original files in their browser
- Access expires automatically β no manual revocation needed; you see every access in your audit trail
- Open the Emergency Share screen
- Select which documents to share and for how long
- Show the QR to your doctor β they scan it, see your records in their preferred language, and the access token expires when the appointment ends
The following invariants are enforced by the architecture β not by policy:
- The server never holds a plaintext document. Encryption happens in the browser before the upload request is initiated.
- The server never holds an encryption key. Keys are derived from passwords client-side and stored only in browser memory.
- Emergency share keys never touch the server. The ephemeral share key is embedded in the URL fragment (
#key=...). URL fragments are never sent in HTTP requests by specification. - The audit trail is append-only.
scan_logsrows are inserted, never updated or deleted. Every access is permanently and immutably recorded.
Password + UserID β PBKDF2-SHA256 (100k iterations) β Master Key
β
ββββββββββββββββββ
β
Per-document AES-256-GCM key
β
βββββββββββββββββ΄βββββββββββββββββ
β β
Wrapped with master key Encrypts document
β β
Stored in document_keys IV + ciphertext uploaded
β to Supabase Storage
β
(useless without master key)
Emergency share:
New ephemeral AES-256-GCM key generated
β
All selected documents re-encrypted with share key
β
Share key β base64 β embedded in URL fragment: /doctor/:token#key=<base64>
β
ββ Fragment is never sent to server (HTTP specification)
ββ Doctor's browser extracts key β decrypts documents locally
ββ Share expires at configured time β key becomes unreachable
| Layer | Technology | Why This Choice |
|---|---|---|
| Frontend | React 18 + TypeScript | Type safety across all crypto operations prevents subtle key-handling bugs |
| Styling | TailwindCSS + CSS variables | Consistent design tokens; automatic dark/light mode |
| Backend | Supabase (PostgreSQL + Storage + Auth) | Row Level Security enforces data isolation at the database layer β no custom middleware to audit |
| Encryption | Web Crypto API (browser-native) | No third-party crypto libraries; no supply chain risk; NIST-approved primitives; hardware-accelerated |
| AI | Google Gemini 2.5 Flash Preview | Multimodal (reads PDFs and images); strongest multilingual generation across African languages |
| Charts | Recharts | Composable with React state; no D3 overhead |
| QR | qrcode (npm) | Client-side generation; share key never sent to any server |
| Build | Vite | Sub-second HMR; optimised production bundle |
| Deploy | Vercel | Edge CDN; zero-config SPA routing via vercel.json |
profiles -- Patient identity and medical profile
documents -- Document metadata (no plaintext content)
document_keys -- AES-GCM keys wrapped with master key (useless without password)
qr_tokens -- Time-limited emergency share tokens
scan_logs -- Immutable access audit trail
health_metrics -- Biomarker cache (Gemini runs once per document)Full annotated DDL is in /docs/schema.sql.
- Node.js v18+
- Supabase account (free tier sufficient for demo)
- Google Gemini API key (free tier sufficient)
# Clone and install
git clone https://github.com/your-username/medvault.git
cd medvault
npm install
# Configure environment
cp .env.example .env
# Add your VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY, VITE_GEMINI_API_KEY
# Start development server
npm run devVITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your_anon_key
VITE_GEMINI_API_KEY=your_gemini_keyRun in your Supabase SQL Editor:
-- Wallet card token
ALTER TABLE public.profiles
ADD COLUMN IF NOT EXISTS wallet_token uuid DEFAULT gen_random_uuid();
-- Scan history
ALTER TABLE public.scan_logs
ADD COLUMN IF NOT EXISTS scanned_at timestamptz DEFAULT now(),
ADD COLUMN IF NOT EXISTS language_used text;
-- Pre-signed share URLs
ALTER TABLE public.qr_tokens
ADD COLUMN IF NOT EXISTS share_signed_urls jsonb DEFAULT '{}';
-- Biomarker cache
CREATE TABLE IF NOT EXISTS public.health_metrics (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
patient_id uuid REFERENCES auth.users(id) ON DELETE CASCADE NOT NULL,
document_id uuid REFERENCES public.documents(id) ON DELETE CASCADE NOT NULL,
test_date date NOT NULL,
biomarkers jsonb NOT NULL DEFAULT '[]',
doc_title text,
created_at timestamptz DEFAULT now(),
UNIQUE (document_id)
);
ALTER TABLE public.health_metrics ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users manage own metrics"
ON public.health_metrics FOR ALL
USING (patient_id = auth.uid())
WITH CHECK (patient_id = auth.uid());src/
βββ pages/
β βββ Landing.tsx # Public landing page
β βββ Auth.tsx # Sign in / Sign up
β βββ Onboarding.tsx # 5-step medical profile setup
β βββ Dashboard.tsx # App home β real-time data, activity feed
β βββ Vault.tsx # Encrypted document store
β βββ Emergency.tsx # Time-limited QR generation + audit trail
β βββ Health.tsx # AI biomarker trend charts
β βββ Profile.tsx # Inline-editable medical profile
β βββ DoctorView.tsx # Public emergency view β multilingual AI summary
β βββ MedicalIDCard.tsx # Permanent wallet card scan page
β
βββ components/
β βββ WalletCardButton.tsx # Canvas 2D PNG export β front + back
β βββ ShareExpiryBanner.tsx # Sticky warning when active QR is expiring
β βββ DocExpiryWarnings.tsx # Stale document alerts by category
β
βββ hooks/
β βββ useAuth.ts # Auth state β onAuthStateChange only, no race conditions
β βββ useHealthMetrics.ts # Biomarker extraction + caching
β βββ useScanHistory.ts # Grouped audit trail with first/repeat detection
β βββ useActiveShares.ts # Active QR polling + expiry warnings
β
βββ lib/
βββ cryptoUtils.ts # AES-GCM, PBKDF2, key wrap/unwrap β Web Crypto API only
| Criterion | Implementation |
|---|---|
| Healthcare / MedTech | Zero-knowledge encrypted health vault. Multilingual emergency doctor share. AI clinical summaries. Biomarker trend charts. Permanent wallet card for unconscious patients. Full access audit trail. |
| AI / ML | Three distinct Gemini applications: multilingual clinical summaries from decrypted documents; biomarker extraction and trend detection from lab PDFs/images; structured clinical summary from patient profile for permanent card view. |
| Cybersecurity | AES-256-GCM. PBKDF2-SHA256 (100k iterations). Zero-knowledge architecture. Ephemeral share keys in URL fragments. Time-limited tokens. Immutable scan audit trail. Row Level Security on all Supabase tables. No server-side key storage β by design. |
| Data Analytics | Health metrics dashboard: AI extracts 20+ biomarkers per lab document, caches results, plots trends across dates with normal/high/low/critical status indicators. Filterable by abnormal results. |
| UX / Design | Mobile-first. Multilingual UI. Emergency flow optimised for high-stress use (large QR, countdown ring, one-tap share). Inline profile editing. Profile completeness guidance. Warm, clinical colour palette. |
- Documents uploaded before the
document_keystable existed cannot be decrypted β re-upload required - The permanent wallet card shows blood type and allergies without authentication by design (MedicAlert model) β patients who want a higher security threshold should use the time-limited QR instead
- Biomarker extraction depends on Gemini's ability to parse the specific lab format β non-standard layouts may miss some values
- Supabase storage signed URLs have a 1-hour ceiling that may be shorter than some configured QR expiry windows
- FHIR R4 import β pull records directly from hospital EHR systems
- NFC wristband β write permanent card URL to NFC sticker, tap to open
- Offline vault β service worker caches encrypted documents for no-internet access
- Next-of-kin delegation β trusted person can generate emergency QR on patient's behalf
- Custom AI prompts β treating physicians can ask specific questions about the patient's history
- Biometric vault unlock β WebAuthn as alternative to password entry
MIT β see LICENSE
MedVault Β· FrostByte Hackathon 2026
AES-256-GCM Β· Zero Knowledge Β· Your keys never leave your device