Skip to content

Slot Engine

The slot engine is the core of The Booking Kit. It takes availability rules, overrides, and existing bookings and produces a list of available time slots.

function getAvailableSlots(
rules: AvailabilityRuleInput[],
overrides: AvailabilityOverrideInput[],
existingBookings: BookingInput[],
dateRange: DateRange,
customerTimezone: string,
options?: SlotComputeOptions,
): Slot[]

Parameters:

ParameterTypeDescription
rulesAvailabilityRuleInput[]Provider’s recurring availability rules
overridesAvailabilityOverrideInput[]Date-specific overrides (block or extend hours)
existingBookingsBookingInput[]Non-cancelled bookings in the date range
dateRangeDateRange{ start: Date, end: Date } to compute slots for
customerTimezonestringIANA timezone for localStart/localEnd formatting
optionsSlotComputeOptionsDuration, buffer, and interval config

Options:

OptionTypeDefaultDescription
durationnumber30Slot duration in minutes
bufferBeforenumber0Minutes of padding before each slot
bufferAfternumber0Minutes of padding after each slot
slotIntervalnumbersame as durationMinutes between slot start times

Returns: Slot[] sorted by start time.

interface Slot {
startTime: string; // UTC ISO-8601
endTime: string; // UTC ISO-8601
localStart: string; // Formatted in customer timezone
localEnd: string; // Formatted in customer timezone
}

Check if a specific time slot is available without computing all slots:

function isSlotAvailable(
rules: AvailabilityRuleInput[],
overrides: AvailabilityOverrideInput[],
existingBookings: BookingInput[],
slotStart: Date,
slotEnd: Date,
): SlotAvailabilityResult

Returns:

type SlotAvailabilityResult =
| { available: true }
| { available: false; reason: "outside_availability" | "already_booked" | "blocked_date" | "buffer_conflict" }

Each availability rule contains an RRULE string, start/end times, and a timezone. The engine expands these into concrete time windows for the requested date range.

// A rule for Mon-Fri 9am-5pm Eastern
{
rrule: "RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR",
startTime: "09:00",
endTime: "17:00",
timezone: "America/New_York",
}

The RRULE parser supports:

  • All standard frequencies (DAILY, WEEKLY, MONTHLY, YEARLY)
  • BYDAY, BYMONTH, BYMONTHDAY, BYHOUR constraints
  • COUNT and UNTIL limits
  • EXDATE exclusions (iCalendar format)
  • validFrom / validUntil bounds on each rule

Overrides modify the base windows for specific dates:

// Block a specific day
{ date: new Date("2026-03-11"), isUnavailable: true }
// Shorten hours on a specific day
{ date: new Date("2026-03-12"), startTime: "09:00", endTime: "12:00", isUnavailable: false }

When isUnavailable: true, all windows on that date are removed. When isUnavailable: false with custom times, the override replaces the base windows.

Existing bookings and their buffer time are subtracted from the available windows. Buffer time is applied symmetrically — bufferBefore minutes before the booking start, bufferAfter minutes after the booking end.

The remaining windows are sliced into individual slots of the configured duration at the configured slotInterval.

The slot engine is a pure function — it takes data in and returns slots out. It makes no database calls. Your application is responsible for:

  1. Fetching rules, overrides, and bookings from the database
  2. Calling getAvailableSlots() with the data
  3. Presenting the results to the customer