Slotwise
Bookings that book themselves.
Slotwise is a scheduling product for businesses that sell time: dentists, salons, consultants, trainers, therapists and legal advisers. Customers pick a service and a slot on a public page; owners and staff run the day from a colour-coded week calendar with availability rules, time off and automated reminders behind it.
- React.js
- Laravel
- PHP
- MySQL
- REST API
Overview
- Business problem
- Small service businesses still run on phone calls, shared spreadsheets and one-size booking forms. Double bookings, back-to-back appointments with no buffer, and no-shows that nobody reminded are routine, and every vertical (a 150-minute balayage, a 45-minute legal consult) needs different rules.
- Product objective
- Give any appointment-based business one place to define services, staff hours and rules, then let customers book only slots that are genuinely free, while reminders and calendar feeds keep everyone in sync.
- Target users
- Owners and front-desk staff of small and mid-sized service businesses, the practitioners whose time is being booked, and the customers booking from a phone.
- Solution
- A Laravel API with an availability engine at its core, a React dashboard built around the week calendar, and a public page plus embeddable widget that share the same slot-search endpoint. Reminders and feeds run from queues and the scheduler.
Project classification
- Project type
- SaaS · Booking platform
- Industry
- Professional services (multi-vertical)
- Frontend
- React SPA with an embeddable booking widget
- Backend
- Laravel, API-first, queues and scheduler
- Database
- MySQL
- Architecture
- API-first SaaS with a rules-based availability engine
User roles
- Customer
- Staff member
- Business Owner
- Platform Admin
My role
- Designed the system architecture and the REST API surface for businesses, services, staff, availability, appointments and customers.
- Modelled the MySQL schema, including availability rules, time off and the constraints used to prevent double booking.
- Built the availability engine and the reminder and ICS-feed jobs on Laravel queues and the scheduler.
- Built the React dashboard, calendar and public booking flow, including the embeddable widget.
- Designed the roles and permissions model (owner, staff, customer, platform admin).
- Product design and UI were produced as part of this concept; there is no production deployment or real user base.
Key features
Week calendar. Interface designed and built by Vikrant. Colour-coded staff, breaks and time off on one week grid. Colour-coded week calendar
The staff calendar is the product's home. Each practitioner has a colour, appointments are placed by start time and duration, and time off and lunch breaks render as blocked areas so a receptionist sees at a glance what can still be sold.
Daily overview. Interface designed and built by Vikrant. Today's schedule, staff load and items needing attention. Daily overview
A start-of-day view for owners: today's bookings, the next appointment, unconfirmed and at-risk bookings, and a per-staff load bar so uneven days are visible before they happen.
Public booking page. Interface designed and built by Vikrant. Service, date and slot picker as a customer sees it. Public booking page with slot picker
Customers choose a service, a practitioner or 'any available', and a day. The slot list comes from the same availability endpoint the dashboard uses, so a slot shown is a slot that can actually be booked.
Services editor. Interface designed and built by Vikrant. Duration, buffers, price and eligible staff per service. Services with duration, buffers and price
Each service carries its duration, a before/after buffer, price, and which staff can perform it. The availability engine reads these values directly, so changing a buffer changes the bookable slots without touching the calendar.
Staff availability. Interface designed and built by Vikrant. Weekly hours, time off and scheduling rules per practitioner. Staff availability rules
Weekly working hours with split shifts, plus dated time-off blocks. Rules are stored as data, not hardcoded, and expressed in the business's local time zone.
Customers. Interface designed and built by Vikrant. Customer list with last visit, next booking and source. Customers and visit history
A searchable customer list with last visit, next booking, booking source and no-show count, so reception can treat repeat customers and repeat no-shows differently.
Reports. Interface designed and built by Vikrant.. Reports and utilisation
Bookings, utilisation by staff, revenue by service and no-show rate over a chosen period, built from appointment records rather than a separate analytics store.
Also in the product
- Week calendar with colour-coded staff
- Availability engine: working rules minus time off minus existing bookings
- Public booking page and embeddable widget
- Services with duration, buffers and price
- Reschedule and cancel with per-business rules
- Automated email and SMS reminders
- Customer records and visit history
- Reports: utilisation, no-shows, revenue by service
- ICS calendar feeds for staff
User flow
- Customer opens the business page and chooses a service.
- Customer picks a practitioner or 'any available' and a date.
- The API returns open slots from the availability engine for that service and date.
- Customer selects a slot and enters name, email and phone.
- The booking is created inside a transaction that re-checks the slot; a conflict returns a clear 'slot just taken' response.
- Confirmation email and the reminder schedule are queued; the appointment appears on the staff calendar.
- Customer can reschedule or cancel from a link in the email, within the business's rules.
- Staff mark the visit Completed or No-show; reports and customer history update.
Technical architecture
- React SPA and embeddable booking widget
- REST API (Laravel)
- Availability engine: working rules minus time off minus existing bookings, with buffers
- Booking service: transactional slot re-check, reschedule and cancel rules
- MySQL: businesses, staff, services, availability rules, appointments, customers
- Queue workers and scheduler: reminders (mail and SMS providers)
- ICS calendar feed per staff member
Database and backend
Availability engine
- Computes open slots as working rules minus time off minus existing appointments, then trims by service duration and buffers.
- Works in UTC internally and expands rules in the business's IANA time zone, so DST changes are handled by the date library rather than by hand.
- One endpoint serves the dashboard, the public page and the widget, so there is a single definition of 'available'.
- Slot search is bounded by a booking window (minimum notice, maximum days ahead) set per business.
Booking and double-booking prevention
- Booking creation runs in a database transaction that locks the staff member's rows for the day and re-runs the availability check.
- A conflict is returned as a normal 409 response with fresh alternative slots, not a generic error.
- Reschedule is a transactional move of an existing appointment, so the old slot is released only if the new one is taken.
- Retried submissions are accepted idempotently using a client-generated request key.
Reminder jobs
- Reminders are queued jobs created at booking time and recalculated on reschedule or cancel.
- Send times are stored as absolute UTC instants computed from the appointment's local time, so a 24-hour reminder lands at the right local hour.
- Each job re-checks appointment status before sending, so cancelled bookings never produce a reminder.
- The scheduler sweeps for stale jobs and for appointments past their end time that have no outcome recorded.
ICS calendar feed
- Each staff member has a tokenised, read-only .ics subscription URL generated by the API.
- The feed is built from appointments on request, with stable UIDs so updates and cancellations replace events rather than duplicating them.
- Tokens can be rotated from settings, which invalidates the previous feed link.
Data model and access
- Core tables: businesses, categories, staff, services, availability_rules, time_off, appointments, customers, reminders, payments, subscriptions.
- Business-scoped queries everywhere; staff see their own calendar by default, owners see all, platform admins are restricted to account-level data.
- Versioned migrations; API responses use a consistent envelope with validated input.
Challenges and solutions
Availability with buffers, breaks and time zones
Expressed hours as rules in local time, expanded each requested day into intervals, subtracted time off, breaks and existing appointments (padded by buffers), then sliced the remainder by service duration on a configurable slot step.
Two customers choosing the same slot at the same moment
The booking transaction locks the staff member's day and re-validates the slot before inserting. The loser gets a 409 with updated slots, so the interface can recover without a page reload.
Rescheduling without losing the original slot
Reschedule is one transaction: validate the new slot, move the appointment, release the old one. A business-level cut-off (for example, no changes within 24 hours) is checked server-side and surfaced to the customer before they try.
Reminders that arrive at the right local time
Reminder instants are computed from the appointment's local time and stored in UTC. Jobs are recalculated whenever the appointment changes and verify status at send time.
Calendar sync that does not duplicate events
The ICS feed uses stable per-appointment UIDs and sequence numbers, so subscribing clients update or remove events instead of adding copies.
One engine for many kinds of business
Verticals differ only in data: duration, buffers, staff eligibility, booking window and cancellation rules live on the service and business records, so a dentist and a trainer run on the same code path.
Results
- Single source of truth for availability across dashboard, public page and widget.
- Double-booking prevented at the database transaction level, not just in the interface.
- Reminder, reschedule and cancel rules configurable per business without code changes.
- A calendar-first interface that stays usable on a front-desk screen and on a customer's phone.
Qualitative outcomes only; no usage or revenue figures.
Visual identity
- Primary #4F3FD0
- Secondary #1F2433
- Accent #C5F04A
- Background #FAFAFC
Manrope (single family, weights for hierarchy). Clock-slot glyph: a rounded rectangle split into two slots, with a wordmark. Calendar-first SaaS: top bar, left navigation and a week grid with colour-coded staff.
Related projects
- Portfolio ProjectRestaurant operations
Seatly
Real-time floor management: live table status, reservation timeline and waitlist for restaurant teams.
- React.js
- TypeScript
- Laravel
- PHP
- MySQL
- WebSockets
- REST API
- Portfolio ProjectRestaurant / hospitality
Tavolo
Restaurant booking platform. Discovery, live availability and a floor-aware dashboard for restaurants.
- Laravel
- PHP
- MySQL
- REST API
- Tailwind CSS
- JavaScript