PORTFOLIO // PROJECT
Clinic Team
Scheduler
A full-stack, role-based staff scheduling platform built for an outpatient physical therapy clinic — from first requirement to production deployment on a custom domain.
I designed, built, and shipped a live web application that runs the clinic's weekly technician scheduling: staff submit availability and time-off in 30-minute increments, a scheduler builds the week across land and pool treatment areas, and a director reviews, edits, and posts the final schedule — with every permission enforced at the database level, not just in the interface.
| Staff | Mon | Tue | Wed | Thu | Fri |
|---|---|---|---|---|---|
| Alex | L7a–3p | L7a–3p | P7a–3p | L7a–3p | L7a–1p |
| Jordan | L9a–2p P2p–7p |
L9a–8p | — | P9a–2p | P7a–12p |
| Sam | P7a–1p | P7a–1p | L7a–1p | P7a–1p | L7a–1p |
| Riley | P12p–8p | P12p–3p | L12p–8p | P1p–8p | — |
SEC 01 // PROJECT OVERVIEW
A scheduling problem every clinic knows.
An outpatient physical therapy clinic scheduled its technician staff the way most small practices do: spreadsheets, texts, and memory. Availability lived in people's heads, time-off requests got lost, and the weekly schedule had no review step before it reached the team — and no record of who changed what.
I built a production web application that replaces that process end to end. Staff enter recurring availability and request time off (full days or 30-minute windows), a scheduler assembles the week across two treatment areas — land and pool — with live conflict warnings, and a director reviews, edits, approves, and posts. Technicians only ever see the final, approved schedule.
SEC 02 // MY ROLE
Product owner, developer, and operator.
This was a one-person delivery. I gathered requirements directly from the clinic's staff roles, designed the data model and approval workflow, built the React frontend, configured the Postgres database with row-level security so a technician physically cannot approve or alter a posted schedule, and deployed the app to production with continuous deployment and a custom domain. After launch, I iterated in short cycles — six production updates driven by real user feedback, including a live data migration that converted the entire scheduling model from hourly to 30-minute precision without losing a record.
SEC 03 // THE WORKFLOW
Availability in. Approved schedule out.
The platform runs a weekly cycle with clear ownership at every step. Nothing reaches the team until it has been reviewed and posted — and once posted, changes flow through a revision process that keeps the current schedule visible until the new one is approved.
-
COLLECT
Availability & Time Off
Staff maintain recurring weekly patterns, one-week exceptions, and time-off requests — full days or partial windows in 30-minute steps.
-
BUILD
Draft the Week
The scheduler assigns staff to 30-minute blocks across land and pool, in bulk or block by block, with live warnings for any conflict.
-
REVIEW
Director Approval
The director sees coverage totals, unresolved conflicts, and a change-by-change diff for revisions — and can edit directly before deciding.
-
POST
Publish to the Team
Approved schedules go live instantly. Staff see a clean week-at-a-glance summary, with the detailed grid one tap away.
SEC 04 // INSIDE THE APPLICATION
One platform, three working views
A representative look at the interface. Switch roles to see how the same schedule is experienced by the people who build it, approve it, and work it.
Add a shift block — assign multiple 30-minute blocks at once
| Time | Mon | Tue | Wed | Thu | Fri |
|---|---|---|---|---|---|
| 1:30 PM | L Alex P Riley | L Alex L Jordan | P Alex L Riley | L Alex P Riley | L Sam |
| 2:00 PM | L Alex P Riley | ⚠ Sam L Jordan | P Alex L Riley | P Jordan | L Sam |
| 2:30 PM | P Jordan P Riley | L Alex | L Riley | P Jordan P Riley | Closed at 6 PM Fridays |
Your week
| Staff | Mon | Tue | Wed | Thu | Fri |
|---|---|---|---|---|---|
| Jordan (you) | L9a–2p P2p–7p |
L9a–8p | — | P9a–2p | P7a–12p |
| Time | Mon | Tue |
|---|---|---|
| 1:30 PM | L Jordan | L Jordan |
| 2:00 PM | P Jordan | L Jordan |
| 2:30 PM | P Jordan | L Jordan |
Request time off
Partial-day requests only block their window — the scheduler can still book the rest of the day.
Coverage summary
Proposed changes
- Riley — Thu 1:00 PM–8:00 PM: added (Pool)
- Alex — Wed 7:00 AM–3:00 PM: moved Land → Pool
- Sam — Tue 2:00 PM–4:00 PM: removed (was Pool)
Decision
The director can also edit assignments directly in review before approving.
REPRESENTATIVE INTERFACE — LIVE PRODUCTION DATA REDACTED
SEC 05 // ROLE-BASED ACCESS CONTROL
Six roles. Enforced by the database, not the buttons.
Every permission is written as a Postgres row-level security policy. Hiding a button is cosmetic — here, a technician's account is structurally incapable of reading a draft or approving a schedule, even if the client is tampered with.
| ROLE | AVAILABILITY & TIME OFF | BUILD SCHEDULES | APPROVE & POST | SEES |
|---|---|---|---|---|
| Technician | ✓ own entries | — | — | Posted schedules only |
| Scheduler | ✓ review & decide | ✓ draft & revise | — | Everything |
| Director | ✓ review & decide | ✓ draft & edit live | ✓ sole authority | Everything |
| Office Admin | view only | — | — | All schedules, read-only |
| Physical Therapist | — | — | — | Posted schedules only |
| PT Assistant | — | — | — | Posted schedules only |
SEC 06 // SKILLS DEMONSTRATED
Skills demonstrated
SEC 07 // PROJECT SUMMARY
Executive summary
I designed, built, and operate a production scheduling platform that a working physical therapy clinic uses to run its weekly staffing. The system covers the full lifecycle — availability, time off, drafting, approval, posting, and controlled post-publication changes — across six user roles, two treatment areas, and 30-minute scheduling precision, with every permission enforced by database-level security. It was shipped fast, then hardened through six production iterations driven by real user feedback.
"This project demonstrates end-to-end ownership: turning a messy, human scheduling process into working software — and then keeping it working, migrating live data, tightening security, and refining the experience as real users pushed on it."