A multi-tenant SaaS that runs an Indian physiotherapy clinic end to end — patient files, attendance, session packages, GST billing, prescriptions and a self-serve patient portal — from one calm, phone-first screen.
The interesting part is the tenancy model: every clinic's data is walled off by Postgres Row-Level Security keyed on the signed-in user, so patient records can never leak across clinics — proven with isolation tests. Money is stored as integer paise (never floating-point rupees), invoices carry GSTIN from day one, and sharing is +91 WhatsApp-native. Physiotherapists self-serve a 14-day trial clinic; a super-admin back-office then activates paid accounts by hand after offline UPI or bank payment, with audited 'view-as' masquerade to support any clinic exactly as its staff or patients see it.
Multi-tenant clinics isolated by Postgres Row-Level Security
Auto File No., QR cards and printable labels for every patient
Attendance by QR scan or File No. that auto-decrements the session balance
GST-ready, paise-accurate billing and recharge packages
Self-serve patient portal — sessions left and prescriptions, no app install
Super-admin back-office with audited 'view-as' masquerade
+91 WhatsApp-native sharing, greetings and marketing
Enforced tenancy in the database rather than the app — Row-Level Security policies keyed on auth.uid() via SECURITY DEFINER helper functions, with automated isolation tests proving data never crosses clinics.
Stored every amount as integer paise and converted only at the input and render boundaries, so invoices reconcile to the rupee and never drift on floating-point math.
Sign-up provisions a real trial clinic in seconds to run on live data; payment stays offline (UPI or bank) and a super-admin activates the account by hand — no card on file, no auto-charge.
Next.js 16 (App Router, React 19 Server/Client Components) on Vercel, with all data in Supabase Postgres. Tenant isolation is enforced in the database by Row-Level Security policies keyed on auth.uid() through SECURITY DEFINER helper functions — not in application code. Three clean layers keep concerns apart: server components and actions render, pure domain functions hold the business logic (unit-tested), and a thin data layer wraps Supabase. Money is integer paise end to end; Razorpay powers public appointment booking via a signature-verified webhook; transactional email goes through Resend. Ships as an installable PWA so the phone camera scans patient QR cards.
Next Project