Skip to content

Slotwise

Open-source booking engine for UK businesses

An open-source TypeScript booking engine: REST API, embeddable widget, owner dashboard and background worker. Never double-books, stays correct across UK clock changes, and never loses an email. 157 tests run by CI on every push.

  • TypeScript
  • NestJS
  • Next.js
  • PostgreSQL
  • Prisma
  • Redis
  • BullMQ
  • Zod
  • Vitest
  • GitHub Actions
Slotwise

Outcome

A booking engine that guarantees no double-bookings at the database level: 100 parallel requests for one slot give exactly 1 success and 99 rejections.

parallel requests for one slot succeeds; the other 99 get 409 SLOT_TAKEN
1 of 100
tests run by CI on every push: 49 engine unit tests and 108 API integration tests
157
for the slot engine to find 30 days of slots for one staff member
~11 ms

Overview

Slotwise is an open-source booking engine for UK businesses that sell 1-to-1 appointments, such as clinics, solicitors, tutors and driving instructors. It has a REST API, an embeddable booking widget, an owner dashboard and a background worker. A business adds one script tag and one HTML tag to its website, and its customers can book appointments from there.

Problem

Most booking code checks whether a slot is free and then inserts the booking. Under load that is not safe: two requests can both see 10:00 as free and both book it. UK clock changes cause a second kind of bug. One night in March has no 01:00–01:59, and one night in October has it twice, so systems that store local times or add hours naively offer slots that do not exist or book the wrong hour.

My contribution

  • Designed and built the whole system myself: data model, NestJS API, Next.js dashboard, embeddable widget and BullMQ worker.
  • Wrote the pure slot engine and its 49 unit tests, covering split shifts, buffers, notice periods, overrides and all four 2026–2027 UK clock changes.
  • Built bookings with database-enforced no-overlap, idempotency keys and an audit log.
  • Built confirmation, reminder and cancellation emails on an outbox, a separate worker and a send log, plus signed webhooks with SSRF protection.
  • Set up GitHub Actions CI that runs typecheck, lint, tests and build on every push.

Technical approach

PostgreSQL, not application code, refuses overlapping bookings, through an exclusion constraint on each staff member's blocked time. Bookings are stored as UTC instants and working hours as wall-clock minutes in Europe/London, and every conversion goes through the Temporal API. A booking change and its outbox event commit together, and a separate worker turns events into emails and webhooks. The slot engine is a pure function with no database, clock or I/O, so it is fast and easy to test thoroughly. Every tenant query is scoped to the business taken from the authenticated request, never from the URL or body.

Engineering highlights

  • PostgreSQL exclusion constraint on staff time ranges: 100 parallel bookings for one slot give exactly 1 success and 99 × 409 SLOT_TAKEN.
  • UK clock changes handled with the Temporal API: no slots in the missing hour in March, and each local time offered once in October.
  • Outbox, separate worker and send log: a crash between saving a booking and sending its email loses nothing, and retries don't send twice.
  • Pure, linear-time slot engine: about 11 ms to find 30 days of slots for one staff member.
  • Multi-tenant isolation: another business's bookings, services or staff return 404, never 403.

Key features

  • REST API with Swagger docs generated from the same Zod schemas that validate requests.
  • Embeddable booking widget: a Web Component in Shadow DOM, about 5 KB gzipped.
  • Owner dashboard: calendar, bookings, services, staff, weekly hours and time off.
  • Confirmation, reminder and cancellation emails with calendar invites.
  • Customer manage link to view, move or cancel a booking.
  • API keys with idempotent booking requests and signed webhooks.
  • Customer data erasure and automatic retention clean-up.

Result

Slotwise is open source on GitHub under the MIT licence. 157 tests (49 engine unit tests and 108 API integration tests against real PostgreSQL and Redis) run in GitHub Actions on every push, alongside typecheck, lint and build.

Development timeline

  • Foundations
    Monorepo, authentication, roles and tenant isolation, with CI running against PostgreSQL 18 and Redis from the start.
  • Slot engine
    Services, staff, weekly hours and date overrides, then the pure slot engine with explicit UK clock-change handling.
  • Bookings
    Bookings with database-enforced no-overlap, idempotency and an audit log; then emails, reminders and the customer manage link.
  • Widget & API
    Embeddable booking widget, hosted booking page, API keys, signed webhooks, customer erasure and the README.