The Patient Portal: From an Agency Shell to a Self-Service Hub (and a Vibe-Coder Case Study)
Part of the Technical Breakdown series on my 4-year engagement with Prestige Men's Health.
Worth being accurate about this one up front: I didn't build the patient portal from zero. The original outsourced agency shipped a first-pass version before I joined, in late 2022. What I did, starting in 2024, was rebuild it on Filament and keep extending it — and this is also the subsystem with the clearest, most concrete evidence of the "vibe coder" hand-off described in the main post, because by mid-2026 the founder, Dr. Joshua Schmidt, was shipping real features into this exact codebase himself.
The 2024 rebuild
The inherited portal was functional but basic. Starting in April 2024, I rebuilt the patient-facing side on Filament — a framework choice that mattered later, because it's the same admin framework the staff-side tooling runs on, meaning portal features and staff features share one component system instead of two disconnected UIs that drift apart over time.
Problem: an access-control edge case worth getting right
Role-based access control on anything patient-facing needs to fail closed, not open — and getting the "which staff role can see which patient data" matrix exactly right across every route is the kind of thing that surfaces edge cases as real usage grows, not during initial testing. One specific fix ("patch 403 forbidden on patient portal") addressed a routing/permission-check gap where a legitimate access path was being incorrectly blocked — the safe failure mode (deny by default) working as intended, just needing the specific permission grant corrected.
// AFTER — app/Policies/PatientPortalPolicy.php (conceptual)
class PatientPortalPolicy
{
public function viewLabResults(User $user, Patient $patient): bool
{
// Explicit, auditable conditions — not an implicit "if admin, allow
// everything" fallthrough that's easy to get subtly wrong as new
// roles get added later.
return $user->id === $patient->user_id
|| $user->hasRole('clinical_staff')
|| ($user->hasRole('front_desk') && $user->can('view-basic-demographics'));
}
}
Access-control code on a patient-facing system is exactly where "fail closed and fix the specific grant" beats "loosen the check until the error goes away" — a stricter default with a correctly scoped exception is safer than a looser default that happens to work for today's role list.
The Copilot-built expansion
One real, verifiable data point: an autonomous GitHub Copilot coding-agent PR (copilot/update-patient-portal-sections, merged April 2026) added entire new portal sections — Rx visibility, lab results, document access — and enabled two-factor authentication on patient accounts, in a single autonomously-generated, human-reviewed PR. That's a meaningfully large feature addition for an agent to execute end-to-end, and it landed the same week as dozens of other autonomous PRs hardening SMS and the Tebra sync described in the other posts in this series.
The vibe-coder case study, made concrete
The main post's claim that Dr. Schmidt became an empowered "vibe coder" isn't a framing choice — it's visible directly in the commit log. In July 2026, under his own name, he shipped a real sequence of features into this exact portal:
Lab-trend graphing on the Lab Results window
An incoming-fax staging/review area
Patient injection-reminder settings
A full patient reorder flow — checkout, pickup-vs-ship selection, charge the card already on file
Staff "View as patient" impersonation, plus a "Set portal password" action, both surfaced directly in the admin Command Center
That last pair is worth dwelling on: impersonation tooling for support purposes is a feature that needs real judgment to build safely (audit trail, scoping, an obvious on-screen indicator that staff are viewing as a patient, not as themselves) — and it was built, debugged, and fixed for an edge case (patients without portal onboarding) within the same week, by the clinic's owner, not by me. That's the actual measure of a successful hand-off: not "the system runs fine if nobody touches it," but "the non-engineer running the business can extend it correctly himself."
This is one of four deep-dives off the main technical breakdown post — the others cover the SMS communication platform, the Kareo/Tebra EHR sync, and the Rx order pipeline.
Comments
No comments yet — be the first to share your thoughts.
Leave a comment
Your comment will be reviewed before it appears publicly.