Double-bookings are usually a configuration issue, not a software bug. Here's the playbook for diagnosing and preventing them.
The 6 causes
1. Same tech, overlapping appointments — a tech is double-booked at 10 AM. Almost always: shop has multiple booking surfaces (public page + manual entry + walk-in) and the conflict check only ran for one of them. 2. Same bay, two services — two different services landed in Bay 2 from 10:00-11:30 because bay assignment is service-specific and the booking flow didn't respect bay capacity. 3. Off-shift booking — a tech is scheduled at 8 AM but their shift starts at 9. Working hours weren't enforced. 4. Google Calendar drift — tech blocked time in their personal Google Calendar, but SalesThumb's calendar integration is currently one-way (SalesThumb → Google/Apple/Outlook, via a subscription feed). Personal-calendar blocks don't flow back into SalesThumb today, so the scheduler has no way to know about them. 5. Blackout not set — shop is closed July 4 but nobody added a blackout for it in SalesThumb, so the public booking page accepted appointments. 6. Buffer time violation — install runs longer than estimated; next appointment was booked back-to-back without buffer.
Fix #1 — Trust the built-in conflict check, and know when it can be overridden
There's no per-surface toggle to enable — every booking path (public booking page, manual entry, walk-in, reschedule) runs the same server-side conflict check at submit time, not just at slot-display time, so a resource-level double-booking is blocked before it saves. If a same-bay/same-tech conflict still lands, the most likely cause is a deliberate override at booking time, not the check being off — the create/reschedule flow has an explicit bypass an operator can use, so double-check whether someone knowingly force-booked over a conflict.
Fix #2 — Keep your bay list accurate
Settings → Installers & Bays. Make sure every physical bay your shop actually uses is listed and marked active — and mark old/decommissioned bays inactive. SalesThumb can only conflict-check against bays it knows about; a bay that was never added, or one still marked active after you converted it to storage, is the most common root cause of a "same bay, two services" conflict.
Fix #3 — Set tech shifts
Employee Schedule (Calendar → Employees tab, or go directly to /app/staff-schedule). Add each tech's shift for the days they work. The scheduler uses these shifts, not a generic hours field, to know when a tech is actually available — a tech with no shift entered for a day can still get booked, since there's nothing to check against.
Also: set unavailability for vacation days here, not in Google Calendar only.
Fix #4 — Set blackouts in advance
Settings → Sales Matrix, in the Estimate scheduler section. Add a blackout for at least:
- Thanksgiving + Black Friday
- Christmas Eve + Christmas Day
- New Year's Eve + New Year's Day
- Memorial Day
- July 4
- Labor Day
- Any shop-specific closures (owner's birthday, anniversary)
Do this in January for the whole year. Block out shop holidays walks through it.
Fix #5 — Pad your service durations, because there's no buffer field
There is no per-service buffer-time setting in SalesThumb. A service has a Duration (min) and that's the whole window the scheduler reserves, so two consecutive 90-minute installs really can be booked back-to-back with nothing in between.
Until a buffer field exists, bake the slack into the duration itself at Settings → Services: if a 90-minute install actually needs 15 minutes of cleanup, photos, and walk-through after it, set the duration to 105. It's blunt — the padding shows up in the customer's estimated time too — but it's the only thing the scheduler will honor.
Two related things that are *not* this:
- Settings → Sales Matrix has an install-time buffer percentage (default 15%) that inflates the kiosk's "Est. time at the shop" figure shown to a customer. It's shop-wide, it's a presentation number, and it does not reserve calendar time.
- Ceramic cure time isn't modeled at all. If a bay has to sit empty for 2-4 hours after a coating, block that time yourself — either in the service duration or as a manual calendar entry on that resource.
When a conflict slips through
If despite everything a double-booking lands:
1. Open the conflicting appointments. Look at the booking source (public page, manual, walk-in, HQ). 2. Check the timeline of when each was booked. The later booking should have failed conflict check — find out why. 3. Reach out to the customer who needs to be rescheduled. Apologize, offer a discount ($20-50 makes most customers whole). 4. File a bug at info@roffik.com with the customer/appointment IDs so we can audit.