Skip to Content
📚 Documentation is in active development — pages marked TODO will fill out over the next few weeks.
BookingsAvailability engine

Availability engine

AvailabilityService.listAvailableSlots(args) is the single source of truth for “is this slot bookable?” — used by the flow’s offer_slots block AND the hosted page’s slot grid.

Pipeline

1. Load service duration + buffer + capacity 2. Load business hours per-day open/close + breaks + holidays 3. Load CONFIRMED bookings in the date range 4. Generate candidates step through each day's open window 5. Filter drop past slots, holiday-day slots, conflicts

Slot step

Defaults to the service’s own duration (clean half-hour grid for a 30-min haircut → 9:00, 9:30, 10:00…). Caller can pass a denser step (e.g. 15 minutes) for finer control.

What blocks a slot

  • Existing CONFIRMED booking at the same time (capacity-aware)
  • Past times — anything before “now”
  • Holiday date
  • Day disabled
  • Outside open hours
  • Inside a lunch / cleaning break

Buffer time after a booking blocks the next slot from starting too soon. Buffer across breaks is allowed — appointment ends at 13:00, turnover runs into the lunch hour, doesn’t matter.

Capacity

Phase 1: capacity always 1, so a single conflicting booking blocks the slot. Phase 2 counts partySize across overlapping bookings vs. capacity, so 4 people can share a “table for 4” slot.

Window cap

Hard cap of 60 days per query. Anything wider is rejected — keeps the slot grid quick to compute even on long-window flows.

Tests

The pure helpers (projectToTimezone, wallClockToUtc, enumerateLocalDays, generateDailySlots, filterOutBookedSlots, filterOutPast) are unit-tested with 24 cases covering DST transitions, holiday boundaries, capacity > 1, breaks, and half-open intervals.

Last updated on