RX Library - Telehealth Platform
A white-label telehealth platform: operators configure a tenant, connect a provider network and a pharmacy, and ship a brand under their own domain. Think Shopify for telehealth.
Role
Frontend & Business Logic
Client
Proventheory
Stack
Next.js, TypeScript, FHIR
Type
Multi-tenant SaaS

1. Overview
One platform, many telehealth brands. RX Library is the platform; RxLibrary is the first tenant built on it and the reference implementation. Future tenants inherit the same infrastructure with their own branding, catalog and provider-network choice.
Patients sign up, complete a medical intake, get matched with a licensed provider, receive a prescription and track fulfillment in one place. Providers work through a clinical queue, and operators manage their catalog and order pipeline from an admin dashboard.
⚠️ The Challenge
Launching a telehealth brand normally means stitching together a provider network, e-prescribing, a pharmacy, payments and a patient portal, and rebuilding all of it for the next brand. The constraints make it harder:
- Regulated, health-adjacent data that must be isolated per tenant and auditable
- Many external vendors that are slow, expensive or unavailable during development
- Three audiences (patients, providers, operators) with very different needs
✓ The Solution
A single FHIR-native codebase where a tenant is configuration, not code. One Next.js application serves every role, every external integration runs mocked until a key is added, and a new brand is a database row instead of a deploy.
2. My Contribution
A large team project developed for the agency Proventheory. I took part in building the frontend and was closely involved in the business logic behind the patient, provider and operator flows. The backend (Medplum bots, integration adapters and infrastructure) was built by Aditya Suri.
3. One App, Several Experiences
A single Next.js application (57 routes: pages and API routes) serves every user. There is one login, and the role is detected from the user's Medplum membership, so each person lands in the right experience. Users with two roles get a context switch in the sidebar.
Patient: Resumable intake, provider matching, prescriptions, billing, chat and a live order tracker.
Tenant admin: Catalog and pricing, branding, and the order pipeline with stalled and needs-review views.
Provider: Clinical queue, encounters, prescribing, and a read-only view of what the patient sees.
Platform owner: A super-admin console for managing tenants across the platform, on the roadmap.



4. Architecture
The platform is a Turborepo monorepo organised in three layers. Every record lives in a single FHIR R4 backend, so patients, practitioners and prescriptions are interoperable by default.
Presentation: The unified Next.js app with its API routes.
Clinical substrate: A self-hosted Medplum server: Patient, Practitioner, Task, Encounter, MedicationRequest, QuestionnaireResponse, Communication and AuditEvent resources, plus subscriptions that trigger server-side bots.
Integration: 14 adapters that connect provider networks, e-prescribing, payments, messaging, video and the product catalog.

5. Key Decisions
FHIR as the database schema
Using FHIR resources instead of a custom schema makes every record interoperable by default and gives the team a standard vocabulary for the business logic.
Mock-first integrations
Every adapter implements the same interface and runs against Mock Service Worker fixtures by default. Adding the environment keys flips that adapter to live, and removing them flips it back, with the same code path in every environment. A fresh clone starts a working platform with zero credentials, and the test suite never touches a real vendor.
A tenant is configuration, not code
A tenant is a FHIR Organization with a configuration extension: slug, brand, legal name, provider network, e-prescribing provider and domain. The tenant is resolved from the request's host and there are no per-tenant branches in the code, so adding a tenant is a database row rather than a deploy. Authority is layered: the platform owns the master catalog and defaults, each tenant picks products, pricing and branding, and tenant clinicians can adapt protocols, with every edit audited.
Automation never prescribes
Bots can only propose a prescription. A licensed practitioner promotes a proposal into an order, which keeps the clinical decision with a human.
6. The Order Lifecycle
Each order is a single FHIR Task whose business status walks through intake complete, provider assigned, consult scheduled, consult done, prescription sent, pharmacy processing, shipped, fulfilled and refill due. Side states such as stalled, needs review, on hold and cancelled catch the exceptions. A state-machine bot rejects illegal transitions and records every change in the audit log. The patient's order tracker mirrors these stages.
Eleven stateless, idempotent bots react to subscriptions, schedules and webhooks: intake-to-order conversion, provider routing, prescription transmission, hourly stall detection, refill and check-in reminders, a month-two renewal pipeline, an hourly catalog sync from Airtable and superbill PDF generation.
7. Integrations
Provider networks: MDI, OpenLoop and Beluga, chosen per tenant.
Prescribing and pharmacies: RXNT e-prescribing and several pharmacy adapters.
Payments and identity: Stripe and Stripe Identity.
Messaging and video: Twilio, SendGrid and Daily.co.
Hardening: Idempotency, retryable-error classification, failure-mode tests for every adapter and signed-webhook verification.
8. Access Control and Infrastructure
Isolation: One parameterised access policy per role scopes every provider and admin query to their organization, and patients only see their own compartment. A live test asserts that a patient gets a 403 when reading another patient's record.
Infrastructure as code: AWS via Terraform: containers on ECS Fargate, a multi-AZ Postgres database, Redis, a load balancer with TLS, a web application firewall, secrets management and alarms.
CI/CD: GitHub Actions deploying through short-lived OIDC credentials, with no long-lived keys.
9. Outcome
3
roles, one app
14
integration adapters
11
server-side bots
800+
unit tests
50+
E2E specs
Key Takeaways
- Standards pay off: Building on FHIR meant the business logic could use an existing vocabulary instead of inventing one.
- Mocks unblock everyone: Mock-first adapters let frontend and business logic move without waiting for vendor access.
- Configuration beats branching: Keeping tenant differences in data avoided a codebase full of per-brand conditionals.