Clinic booking apps look like a calendar with a "Book" button. In practice, the hard parts are elsewhere: how you model free time, how you stop two patients from taking the same slot, how reminders reach people in the right time zone, and how you keep health data out of places it shouldn't be.
I'm a freelance Flutter and WordPress developer in Famagusta, North Cyprus, where many clinics treat local patients and visitors from abroad in the same week. Here is how I structure these apps.
Model availability, not appointments
Storing only appointments and "calculating" free time on the client gets messy fast. I keep three things on the server:
- Schedules: each practitioner's working hours per weekday, per branch.
- Exceptions: holidays, sick days, a surgery that blocks the afternoon.
- Bookings: practitioner, branch, start, end, treatment, status.
Free slots are generated on the server for a requested day: working hours minus exceptions minus existing bookings, cut into pieces of the treatment's duration plus a buffer. The app only displays what the server returns.
Never trust the client with the last slot
Two patients tapping the same 10:30 slot at the same moment is not a rare edge case on a Monday morning. The booking must be created in a transaction (or with a unique constraint on practitioner + start time) on the server. With Firestore, that means a transaction that reads the slot document and fails if it already exists. With Supabase / Postgres, an exclusion constraint on a time range does the job elegantly:
ALTER TABLE bookings
ADD CONSTRAINT no_overlap
EXCLUDE USING gist (
practitioner_id WITH =,
tstzrange(starts_at, ends_at) WITH &&
) WHERE (status IN ('pending', 'confirmed'));
The app then simply handles the error with "This time was just taken, here are the next free times".
Time zones: store UTC, show local
Patients book from abroad before they travel. Store starts_at in UTC, show it in the clinic's time zone with the zone name visible ("10:30, Cyprus time"), and schedule reminders from the server, not with local notifications calculated on the phone. A reminder the day before and a short one two hours before cuts no-shows noticeably.
Forms before the visit
Intake forms are where privacy matters most. My rules:
- Collect only what the clinic actually needs.
- Store answers server-side with strict access rules (staff role only), never in local storage or analytics events.
- No health details in push notification text: "You have an appointment tomorrow at 10:30" is fine, the treatment name is not.
One codebase, two front doors
New patients usually find the clinic through Google and book on the website, while returning patients use the app. Both talk to the same booking API, so the calendar is always the single source of truth. Flutter covers Android and iOS from one codebase, and the website can be WordPress with a small booking front-end calling the same endpoints.
The business-side version, for clinic owners, is here: Clinic Appointment App in North Cyprus: Fewer No-Shows, Happier Patients. How do you handle slot collisions in your booking apps?
Top comments (0)