A barbershop running a full GoHighLevel booking calendar had no systematic way to take a walk-in customer without double-booking a barber or making them guess their wait. ChairFlow is a queue that reads the shop's existing calendar and slots walk-ins into the real gaps, with no second calendar for staff to maintain.
The problem
The booked calendar and the walk-in queue were two separate problems solved the same way: guesswork at the front desk. A barber's booked appointments lived in GoHighLevel, but a walk-in customer wasn't in that system at all, so fitting them in meant a staff member checking the calendar by eye and estimating a gap. Get it wrong and a barber is double-booked, or a customer waits far longer than they were told. None of it fed back into the calendar the shop already used for everything else, so the queue and the bookings never reconciled with each other.
What we built
A calendar-aware queue that sits on top of the shop's own GoHighLevel calendar rather than replacing it. Customers self-check-in at a kiosk, reachable by QR code, with no staff member needed to start the process. A front-desk board shows the live queue and lets staff assign barbers, and accepted walk-ins are written back to GoHighLevel as real appointments, so the shop's calendar stays the single source of truth. Notifications go out through GoHighLevel's own SMS, not a separate messaging system layered on top.
Under the hood
The scheduling decision, the one piece of logic the business can least afford to get wrong, is a pure function: it takes the current time, the barbers, the services, the existing bookings and the walk-in queue, and returns an assignment. No side effects, no hidden state, and it runs identically whether it's backed by an in-memory store or the production Postgres database, and whether it's talking to a mock calendar or the live GoHighLevel API. That's deliberate: the same tested logic that runs in a demo runs in production, so nothing behaves differently the day it goes live.
The system is 14 API routes and 8 Postgres tables: settings, services, barbers, business hours, bookings, walk-ins, an SMS log and GoHighLevel token storage. A webhook endpoint verifies a signature before trusting anything GoHighLevel sends it, and always acknowledges with a 200 regardless of what happens next internally, so a business-logic error on our side never turns into a retry storm on GoHighLevel's side. A separate reconciliation job re-pulls the day's appointments from GoHighLevel on a schedule, so a missed or duplicated webhook gets corrected automatically rather than silently drifting.
A single flag switches the whole system into a zero-credential demo mode: an in-memory store and a mock GoHighLevel calendar, so the full flow, kiosk, board, SMS notifications and all, can be built, tested and demoed without a single real credential in play, even sitting next to a .env file that has them. It's built white-label from day one: bringing on a new shop is copying the repository, standing up a new database, and editing one configuration file, not forking the scheduling logic per client.
What changed
A fully-booked shop can take a walk-in without a front-desk spreadsheet or a staff member doing calendar arithmetic in their head. The queue and the booking calendar are the same calendar, so there's nothing for two systems to disagree about. The build is on track to launch on 1 August 2026, with the underlying platform designed from the outset to be reusable, white-label infrastructure rather than a one-off build for a single shop.
