PRODUCT BUILD
Orvia
A week of retail shifts is a constraint-satisfaction problem. Most scheduling software gives you a better spreadsheet, Orvia generates the answer.
Problem
A friend spent three hours a week rebuilding the same schedule by hand
She managed three retail stores and built every week’s shifts in Google Sheets, juggling availability, roles, hour caps, and fairness. Her options were a spreadsheet or enterprise software with a five-figure contract.
Challenge
Schedules run on rules, but people run on exceptions
Hour caps and role coverage can be coded. “She can’t open Tuesdays because of school pickup” is harder, and every manager has a list of them.
Solution
One click drafts the week; the manager fixes what’s off
I started with the data. A new store, role, or hire is just more data in Supabase, so the schedule can grow without a rebuild.
Then the rules. I wrote each one in plain text and had AI turn it into code. Every new corner case broke something else, so I left the last mile to the manager. Better obviously partial than confidently wrong.
1–3 setup + state init
workers, templates, recurring assignments, hours
→ exclude manager + inactive
→ keep cross-location shifts (conflict guard)
→ new ScheduleGenerationState
4 processRecurringAssignments() ← highest priority
stable weekly patterns placed first, slots locked
5 processPairedPrepBaristaShifts() ← specific location only
prep + barista paired together
6 assignLeads()
open: start < 12:00 · close: end ≥ 21:00
tie-break: prior week → fewest hours → highest job_level
7 assignDynamicShifts()
remaining unfilled slots
tie-break: fewest hours → highest job_level → unassigned ⚠
8 saveSchedule()
→ scheduled_shifts (write to Supabase)
→ shift_assignments (write to Supabase)
Generation pipeline. Setup in 1–3, assignment phases in 4–8.
The design system grew out of the screens. As patterns repeated, I pulled each color, type role, spacing value, and corner radius into a single :root block and documented it alongside the product, so designing in code wouldn’t drift into AI defaults.
Color tokens
Primary
Categorical
Neutral
Semantic
Typography tokens
Manrope. A geometric sans-serif with slightly rounded strokes and open apertures. Designed to stay readable at small sizes without feeling cold.
Spacing tokens
Layout, used directly
Border radius tokens
The obvious product is a grid you fill in cell by cell. Orvia fills the week in one click, and the manager edits from a sorted list rather than dragging name pills, which turn into a wall to scan at fifty people.
Clicking any cell opens the edit modal — an alphabetically sorted list to reassign the shift
Impact
Three hours a week, down to fifteen minutes
Orvia drafts a full week across her three stores in a couple of seconds. The rest of her time goes to the human exceptions no rule captures.
Regional manager dashboard — three locations, current-week staffing coverage at a glance
Where it could go
Managers could type the exceptions
Generation would stay rule-based. But “Maria can’t open Tuesdays anymore” could update her availability on its own, since turning plain language into structured fields is a good fit for an LLM.