I'm always excited to take on new projects and collaborate with innovative minds.

Email

joshuerubio@gmail.com

Social

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
RX Library platform
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.

Patient experience
Patient experience: chat with the care team and order tracking
Operator dashboard
Operator dashboard: order pipeline health
Provider portal
Clinical portal: the provider queue
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.

RX Library architecture
Platform architecture
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.