GAS Scheduling
Coming. You'll click through GAS Scheduling right here in your browser.
The Problem
She managed a roster of healthcare providers across seven locations through text messages and a spreadsheet β administrative hours that, as a practicing anesthesia provider herself, came directly out of the time she could have spent taking shifts.
What I Built
I built the scheduling system that replaced them. Separate dashboards for administrators, managers, and providers. Rules that catch double-bookings before they happen. Timesheets and invoices drawn from the same underlying records. Email notifications sent in batches. Solo. 27 days.
What Happened
Live across seven locations. Eleven times more shifts now come from providers requesting and managers approving than from administrators handing them out by hand β the system didn't just digitize the old workflow, it changed how the team works.
Next.js Β· Supabase Β· Vercel
Origin
Elizabeth came through a chain of intermediaries β a referral, not a cold pitch. By the time we spoke, another vendor had already given her a price. I didn't argue on price. I changed what I was showing her. Instead of a quote on paper, I built a working prototype β something she could click through β on my own time, before any deal. By the time the conversation got serious, she had already touched the thing.
The work I did before any building was listening. I told her I couldn't design the right system without understanding the business β the operations, the daily shape of it, what her managers actually did. She answered in long messages and a briefing document. From there, the system grew. Every part of it β the kinds of roles people had, what each person could see, how messages got sent, how invoices got prepared β came from her words about how the business actually ran. The shape of the software followed the shape of the work, on purpose, even where it was invisible to her.
How the system thinks
A few of the choices inside this system are worth pointing to, because they say something about the rest.
Take double-booking. It is treated as a wall, not a warning. A provider can request several shifts on the same day β the first one to confirm wins. But once one is confirmed, no other request can sneak through. Not even an administrator can quietly overwrite it. The same rule is enforced in three places at once: at the moment someone clicks, again when the confirmation runs, and a final check inside the database itself that catches anything that bypassed the first two. It is overkill on purpose. We knew the same rule was now sitting in three places β that is a kind of debt, and we wrote it down in the roadmap as something to clean up later when another feature gives us a reason. Deliberate, not careless.
A second principle: "freedom before commitment, locked after." Before a shift is confirmed, providers and managers move around freely. After it is confirmed, two parties depend on it being there. Only an administrator can break it, and only with a logged reason. Underneath that policy is a quieter mechanic: every time something tries to change a confirmed shift, the system checks that nothing has shifted underneath since the last look. Without that check, two administrators acting at the same time could accidentally revive a shift that had already been cancelled β bringing a dead appointment back to life. The rule reads like a policy. The code reads like an accountant's discipline.
Notifications work in batches, with one exception for emergencies. The email service we use caps everyone at two messages per second. Send faster and the messages start getting rejected. So the system sends them one after the other with a small gap β partly to stay within the limit, partly because a provider does not want ten emails at once when a schedule shifts. The exception: any shift starting within the next seven days skips the queue and goes out immediately. That is the case where being late is genuinely expensive.
Invoices, in this system, are not a separate thing. They are the same timesheet, rearranged. Each timesheet groups a provider's hours by week. Each invoice groups those same hours by location and week, totals them, and exports to QuickBooks for accounting. Because they are the same underlying data, there is no risk of the two falling out of sync. They cannot disagree. They are the same.
The most useful reliability story in the whole project lives here. The person doing the bookkeeping had permission to read the timesheet records but not to change them. When she clicked "mark this invoiced," the database's security layer would silently refuse her edit β quietly, with no error message β and the screen would still say the action had succeeded. Nothing was actually being marked. The fix was to route that one action through a stricter path: the database now confirms exactly how many records were touched, and complains loudly when the number is wrong. A failure that had been silent was rewritten into a failure that would be obvious. Most reliability work looks like this. Not new features β removing a kind of confusion.
Two corrections, both in week one
Across the build, the database changed shape about fifty times. Almost all of those changes added something β a new piece of information, a new way of looking something up, a new starting value. Almost nothing was built and then unbuilt. But two foundational assumptions broke hard in the first three weeks. Both came from the same cause. I had started from a generic starting point β built quickly with the help of Claude Code β that carried the usual assumptions a software template carries, and those assumptions did not survive contact with an actual anesthesia staffing practice.
The first was login. The starting design assumed the system would run on shared devices in clinics β providers picking their name from a dropdown and entering a short code, managers entering a passcode for their location. Within the first week, that was thrown out and replaced with real per-person email and password logins. The whole identity model was rebuilt from the start.
The second was timesheets. The starting structure had been shaped for hourly workers β clock-in, clock-out, breaks tracked, hours counted. The reason I changed it is written as a note inside the change itself, in plain prose: GAS providers are trusted professionals who report their own hours. They do not clock in or out. They do not count breaks. The structure had been built for a kind of worker GAS does not have. The change aligned the database with the actual shape of the work.
Both corrections were cheap because they happened early. That is the pattern: build a thick foundation quickly, prune the wrong assumptions when they meet the real business, then move forward in a straight line. The clearest reasoning in this entire project does not live in change summaries. It lives in prose I wrote inside the change files themselves, in the design notes, and in the documents that justify decisions. That kind of writing β slow, in your own words, while you are inside the work β is what evidence of a thought-through system looks like.
What changed after launch
Seventy-eight days after going live, the system had processed 191 shifts. 128 were confirmed. The rate at which open shifts got filled rose from 56% to 67% over six weeks. The roster of active providers doubled, from nine to eighteen. The time it took a manager to respond to a request dropped from about 28 hours to under 8. April was the busiest month: 50 shifts, roughly three times March.
The most interesting number is not the volume. It is the ratio. The new pattern is: a provider sees an open shift, asks for it, a manager approves. That happened 54 times. The old pattern β an administrator manually assigning a shift to someone β happened only 5. Eleven to one. The system did not just digitize the way the team used to work. It moved the work away from the administrator and out to the people closest to it. The way the team operates changed.
Elizabeth, the founder who commissioned this to lighten her administrative load, is still one of the three busiest shift takers in her own system. The time the system gave back to her was not spent doing less. It was spent doing the work she had always been trained to do.
The system runs across seven locations today. Three of those are quiet, waiting for their managers to start using it. There is room to grow β that headroom was designed in β but for now the growth is in the number of providers and the number of shifts, not yet in new geography.
On building
There was an incident I want to mention. During testing, four real providers received real emails. I had left some real contact information in the test database. I noticed it in a log on my screen and stopped the process. Some emails had already gone out. I asked the intermediary to message the providers and tell them it had been a test. The response was a laugh and an "it's okay." There was no real harm. I sent a follow-up email asking them to ignore the previous one. By the end of that day, the test database held no real contact information at all. The only real names left were my own and Elizabeth's. The rest were placeholders. A small story, but a permanent lesson.
If I were asked what I would do differently, the honest answer is nothing. Not because there is nothing to learn β but because the corrections that needed to happen happened during the build, while changing them was still cheap. The two corrections in week one are the evidence: not failures of judgment, but a way of working that does not carry forward bad assumptions for the sake of having decided early.