Best-practice architecture for a regulated telehealth + commerce platform
Revéra is a regulated, two-sided clinical-commerce platform where every purchase is gated by clinical state: a client can only buy what they've been prescribed and cleared for. The best-practice answer for that is not two systems (a WordPress/Shopify store glued to a separate clinical app), but one application on one database: Next.js + managed PostgreSQL, SA-hosted, holding commerce and medical data together.
The earlier plan led with WooCommerce because, for a normal agency, it's the fastest, cheapest, most familiar way to ship. For a regulated, prescription-gated platform that rationale doesn't hold: we build the architecturally correct thing from the start. A welcome side-effect: there's no WordPress to migrate off later, so the confusing "Phase 1 then rebuild" story disappears. It's one codebase that grows, nothing thrown away.
"Can this client buy this product?" depends on their prescriptions and their contraindication flags. With two separate systems you must continuously sync that eligibility across a boundary: a fragile bridge that can drift. With one app and one database, the bridge disappears:
eligible = has_valid_prescription(client, product)
AND NOT exists(absolute_block rule
matching client's flags for product) One source of truth. One audit trail. Row-Level Security over everything: a doctor's queries can only ever return their own patients; a client sees only their own records; the pharmacist sees only the dispensing queue. That is the strongest possible POPIA posture, and it's only clean when it's one database.
| Layer | Choice | Why |
|---|---|---|
| Frontend + API | Next.js (App Router), TypeScript | Built for an authenticated, role-specific portal. Server Components keep medical data server-side; middleware enforces access at the edge. |
| Database | Managed PostgreSQL in SA (AWS af-south-1 / Xneelo) | One DB for commerce + clinical → eligibility is a query, not a sync. Row-Level Security, column encryption for notes, append-only audit triggers. Managed Postgres on SA soil: data stays in-country, with no database infrastructure to self-host or patch. |
| Auth | Auth.js + MFA | Roles: client · doctor · pharmacist · admin · information officer. |
| Commerce | Built into the app (gated catalogue, cart, order state-machine, subscriptions) | The catalogue is small and every purchase is clinically gated: a generic store is the wrong shape. Medusa.js is the sanctioned drop-in if commerce ever outgrows the MVP. |
| Payments | Peach Payments / Paystack (ZAR + tokenised recurring) | The gateway handles money, PCI & recurring; the app only orchestrates. Stripe is out: no SA merchant settlement. |
| Video consults | LiveKit / Jitsi: self-hosted in SA | Embedded in the portal and SA-resident, with no Google Workspace dependency. Record only with explicit consent. The doctor runs the consult, then issues the script in-app. The script + record always stay in our SA database. |
| Booking | Native: built into the app & database | Per-doctor availability and slot booking built directly into the platform (a PostgreSQL bookings table with an overlap-exclusion constraint that makes double-booking impossible): no third-party scheduler, no per-seat fees, no Workspace. Books the consult, mints the video room on the same record and keeps every booking inside our SA database so all patient data stays in-country. |
| E-prescriptions | AES via TrustFactory / LAWtrust | A drawn-signature PDF is not a valid SA e-script. ECTA s13 advanced e-signature is mandatory. |
| Hosting | SA: Xneelo managed / AWS af-south-1 | Sidesteps POPIA s72 cross-border analysis. Encrypted at rest, daily backups, monitoring. Managed, not a raw VPS. |
Data-driven, all in the one database, so a clinician can maintain the rules without a developer:
Answers stored structured; each maps to boolean flags (pregnant, hx_mtc, on_anticoagulants…). Doctor-overridable: clinical judgement beats the form.
product × flag → block / review / warn, editable in an admin UI. So a SAHPRA reclassification is a config change, not a code deploy.
AES-signed, immutable, hashed. Issued by the doctor at the consult; the key that unlocks purchasing.
The catalogue/checkout reads it directly. requires_review/warn surface on the doctor dashboard, preserving clinical override (POPIA s71 / HPCSA 5.5).
Weak for medical records, immutable audit, AES scripts and fine-grained access; a different ecosystem from the clinical app. Its only edge was agency PHP speed, which doesn't outweigh building the clinical core correctly from the start.
Its terms prohibit prescription products; no true per-client per-product purchase block; not self-hostable / not POPIA-controllable.
Can't self-host → fails the SA data-residency requirement; no agreement to lawfully process medical data; total lock-in.
Doesn't support SA-domiciled merchants for ZAR settlement. We use a SA gateway (Peach / Paystack) instead.
The platform can't be the seller of medicine. Every order holds for a licensed-pharmacy partner's dispensing approval before fulfilment, an order-state-machine requirement, fully audited.
Scripts are signed with an accredited advanced e-signature (TrustFactory / LAWtrust) so they're legally valid. Almost no competitor does this.
A real video consult and live clinical evaluation: never questionnaire-only prescribing (HPCSA 5.5) and never exclusively virtual (HPCSA 3.8).
SA hosting, RLS, encryption-at-rest, append-only audit, granular consent, operator agreements, a named Information Officer.
These are the client's to secure (legal opinion, pharmacy partner, doctors, AES provider). We facilitate at Discovery and architect for them. They're also the competitive moat: the market leader has none of them.
Indicative monthly infrastructure cost, in ZAR, excl VAT. These are Revéra's third-party running costs (hosting + services the platform consumes). They are entirely separate from what you pay Brightwork: the one-time build fee and the monthly managed-services retainer. Brightwork's own costs (our labour, AI tooling and dev infrastructure) are covered by those fees and never appear here. Building booking natively and self-hosting open-source video (LiveKit / Jitsi) means no per-seat SaaS bills and no Google Workspace dependency: you pay mainly for the SA server and its bandwidth.
| Component | Launch / low volume | Growing / at scale | Notes |
|---|---|---|---|
| SA hosting + database | R1,000–R3,000 | R6,000–R15,000 | App + managed PostgreSQL on one SA server / region (Xneelo or AWS Cape Town). Grows with traffic & data volume. |
| Scheduling (native, in-app) | included | included | Built into the app and database: no third-party scheduler, effectively zero marginal cost. |
| Video consults (LiveKit / Jitsi, self-host) | R500–R1,500 | R3,000–R8,000 | Bandwidth-driven, SA-resident, embedded in the portal. No per-seat fees and no Workspace. |
| Transactional email | R0–R300 | R500–R1,200 | Order / consult notifications (Resend / SES). Free tiers cover launch. |
| Backups · monitoring · CDN/SSL | R200–R600 | R800–R2,000 | Cloudflare free tier + automated encrypted daily backups. |
| Indicative fixed total | ~R2,000–R5,000 | ~R10,000–R25,000 | Per month, excl VAT. Excludes the usage-based items below. |
Payments: Peach / Paystack take ~2.85–3.5% + ~R1–2 per transaction; some plans add a small monthly fee (~R0–R500). AES e-scripts: LAWtrust / TrustFactory charge per signature (setup + per-script: quote from provider). SMS / WhatsApp: optional, per-message (Clickatell / Twilio). These only rise as volume, and therefore revenue, rises.
Indicative only. Final figures depend on traffic, consult volume and chosen providers, confirmed at Discovery. The leanest launch (native booking + Jitsi on a single SA server) sits at the bottom of these ranges; higher consult volume on LiveKit sits higher.
The platform we build and launch comes first: a functional MVP we then polish into a live, trading platform. Future possibilities are optional later enhancements, layered onto the same app.
The platform you have asked for, delivered as a functional MVP and then polished to live: accounts, questionnaire, contraindication engine, gated checkout, pharmacist hold, booking, video, doctor dashboard, AES scripts, POPIA baseline, ZAR payments, refills.
Optional later enhancements, not included in the monthly and scoped and quoted separately when you want them: automated refills + dunning, advanced dashboards, cross-sell intelligence, analytics, observability, SEO/content engine.
Same app grows. The core ships to revenue; future possibilities layer on later when you want them, never a rebuild.