FHIR Export (meds / appointments / logs) + Provider-share session
#34 opened on Oct 30, 2025
Repository metrics
- Stars
- (30 stars)
- PR merge metrics
- (PR metrics pending)
Description
Summary
Let a user click “Share with my doctor” and generate a short-lived, read-only view of their key health data (medications, appointments, health logs) and optionally download it as FHIR (R4) so it can be dropped into an EHR. This makes SymptomSync way more useful in real clinical convos (“here’s my meds + symptoms for the last 30 days”).
Why
- Right now data lives in Supabase and is great for the user, but it’s awkward to hand to a provider.
- Clinics speak FHIR. We don’t have to support all of it — just the minimum useful resources.
- Short-lived, scoped sharing avoids “give me your login” nonsense.
Scope (MVP)
-
Export surface
- Meds →
MedicationStatement - Appointments →
Appointment - Health logs (symptom, mood, severity, notes) →
Observation
- Meds →
-
Period filters
- “Last 7 days”, “Last 30 days”, “All”
-
One-click download
- JSON bundle (FHIR R4
Bundleof the above)
- JSON bundle (FHIR R4
-
Share session
-
Create a row like
shared_sessionsin Supabase:id(uuid)user_idexpires_atscopes(e.g.["meds","appts","logs"])
-
Generate share URL:
/share/{id} -
RLS: row must be readable without auth but only if
now() < expires_at
-
-
Read-only page
- Next.js route that shows meds / appts / logs nicely
- Banner: “Data shared by {first_name} – expires in X minutes”
- No edit/delete buttons
Non-Goals (for later)
- Bi-directional FHIR (import)
- OAuth2 / SMART on FHIR
- HIPAA BAA story
Data model changes (Supabase)
create table public.shared_sessions (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references auth.users(id) on delete cascade,
scopes jsonb not null default '["meds","appts","logs"]'::jsonb,
expires_at timestamptz not null,
created_at timestamptz not null default now()
);
RLS (outline):
- policy 1 (owner): user can insert/select own sessions
- policy 2 (public read):
using (expires_at > now())for anonymous to read just the shared session + related views (you can materialize a view that joins meds/appts/logs filtered byuser_idand time window)
UI/UX
-
In Dashboard → “Export & Share”
- [Select period] [Select data types]
- Button: Generate share link
- Button: Download FHIR JSON
-
After generate → toast with copyable link
FHIR Mapping (minimal)
-
MedicationStatement
status:activesubject:Patient/{user_id}effectiveDateTime:medication_reminders.start_timemedicationCodeableConcept.text:medication_reminders.med_namedosage.text:medication_reminders.dosage
-
Appointment
status:bookedstart/end: fromappointment_remindersdescription: notes / provider
-
Observation
status:finalcode.text:SymptomSync LogvalueString: symptom / mood / noteseffectiveDateTime: log timestamp
Dump them into:
{
"resourceType": "Bundle",
"type": "collection",
"entry": [ /* MedicationStatement | Appointment | Observation ... */ ]
}
Acceptance Criteria
- User can generate a share link that works in an incognito window.
- Link stops working after
expires_at. - User can download a FHIR JSON file; file contains at least 1 resource per existing record in the chosen window.
- Docs updated (
README.md+ maybeARCHITECTURE.md) to explain data flow + RLS note. - Jest test for the FHIR serializer (given mock meds/logs → expect valid bundle shape).
- Lint & CI pass.
Nice-to-have (later)
- Add ICS to the same screen so providers can drop appts into their calendar.
- Add a “share again” button to re-extend expiry.
- Add field-level masking (don’t include notes if user unchecks it).