A booking page bought once rather than rented: availability, calendar connections, paid bookings and a simple page, at a fraction of the usual price.
Build me a booking page that replaces TidyCal and Calendly: my real availability, somebody picks a slot, both calendars update, nobody emails about times. STACK - Node 20+ with Fastify, server-rendered HTML - SQLite through better-sqlite3, WAL mode - CalDAV or the Google Calendar API for the calendar link, and .ics for everything else - Caddy in front THE DATA MODEL - users: id, email, name, timezone, slug, avatar_path - event_types: id, user_id, slug, title, description, duration_minutes, buffer_before, buffer_after, min_notice_minutes, max_days_ahead, location_kind, location, is_active, colour - availability: id, user_id, weekday, starts_at_local, ends_at_local — the weekly pattern - availability_overrides: id, user_id, date, starts_at_local, ends_at_local, is_closed — holidays and one-off changes - bookings: id, event_type_id, invitee_name, invitee_email, invitee_timezone, starts_at, ends_at, status, answers_json, cancel_token, created_at, cancelled_at, rescheduled_from_id - calendar_connections: id, user_id, kind, credentials_encrypted, calendar_id, read_busy, write_events - Everything stored in UTC; the local pattern is stored as local time plus the user's zone, because 9am stays 9am across a clock change SLOT COMPUTATION, WHICH IS THE WHOLE PRODUCT - Start from the weekly pattern, apply overrides, subtract busy blocks from every connected calendar, subtract existing bookings with their buffers, apply minimum notice and maximum horizon, then slice into slots of the event's duration - Slots align to the hour or half hour by default, not to the first free minute - Compute in the owner's timezone, present in the invitee's, and never let the two conversions happen in different places in the code - Cache nothing that a calendar can change underneath you; a busy check is one request per calendar per page load, and the page says when it was last refreshed - The double-booking guard is a unique constraint on (event_type_id, starts_at) plus a re-check inside the transaction that writes the booking. A booking page that can double-book is worse than no booking page BOOKING - Pick a day, pick a slot, give a name and an email, answer any questions the event type asks, confirm - The invitee's timezone is detected and shown prominently, with a switcher, because the single most common failure here is a meeting booked an hour out - Confirmation with an .ics attached, correct VTIMEZONE, stable UID, and the organiser set - Reschedule and cancel from a signed link that never expires, both of which send an update with the same UID and a higher SEQUENCE - A cancelled slot returns to availability immediately THE CALENDAR LINK - Read busy from as many calendars as the owner connects; write the booking to exactly one - Store credentials encrypted at rest, and say in the README where the key lives - A calendar that fails to answer blocks bookings rather than showing slots it cannot verify — being unavailable is recoverable, double-booking is not - Two-way: an event created in the calendar makes those minutes unavailable within a minute MORE THAN ONE PERSON - Round robin across a group, with a rule: least recently booked, or most available - Collective: a slot exists only when everybody in the group is free - Both are one flag on the event type and one change to the slot computation, not a second product MONEY, IF NEEDED - Optional payment before confirmation through Stripe Checkout, with the webhook confirming — never the redirect - A slot is held for ten minutes while payment completes, then released NOTIFICATIONS - Confirmation to both sides, reminders at the intervals the owner sets, a message on cancellation or reschedule - Reminders from a worker that wakes every minute and is safe to run twice: mark sent inside the sending transaction - Every email states the time in both timezones THE INTERFACE - The booking page is one column: the days, then the slots, then the form. It is opened on a phone more often than not - Times in big type. The timezone under them, always visible - The owner's admin is one page per event type plus one weekly grid for availability - Dark and light, one accent OPERATIONS - .env: DATABASE_PATH, BASE_URL, SMTP_URL, ENCRYPTION_KEY, GOOGLE_CLIENT_ID and SECRET, STRIPE keys - Migrations on boot, each once - Nightly backup off the machine, restore script - Health endpoint that checks the database and one calendar connection WHAT MATTERS MOST Slot computation and the double-booking guard. Write those first with tests: a week with an override, a clock change, two calendars, and two people booking the same slot in the same second. Everything else is forms. Give me the repository, migrations, .env.example, a seed user with two event types, and a README with deploy steps behind Caddy and instructions for connecting a Google calendar.
What you lose
- A one-off price that no build can beat on cost
- Calendar connections already written and maintained
- Paid bookings through Stripe without configuration
If you would rather not build
- A booking page you write, which the prompt covers
- TidyCal itself, which is genuinely cheap
What it costs
read from their page 17 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $2.50/mo | — | 17 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
Easy!Appointments
$0A booking system that runs on ordinary shared hosting.
alextselegidis/easyappointmentsfree · open source
Why this verdict
our own opinion · changed only by a person
84/100
Verdict yes at 84 for control rather than cost — a one-off $29 is hard to beat. The daylight-saving tests are the part to actually write.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about TidyCal
answered from the record above
Is TidyCal free?
No — the plan we track is $2.50 a month. A one-off lifetime purchase of around $29 rather than a subscription; the figure shown spreads that over a year.
Can you replace TidyCal by building your own?
YES. Replaceable in one session with an AI coding agent. Replacement score 84 out of 100, build time one session. Read what you lose before you decide.
How much does TidyCal cost?
$2.50 a month on Lifetime — $30 a year. Recorded 10 Aug 2026.
What do you lose by replacing TidyCal?
A one-off price that no build can beat on cost; Calendar connections already written and maintained; Paid bookings through Stripe without configuration. If any of those carry weight for you, keep paying.
Is there an open-source alternative to TidyCal?
Yes: Cal.com, Easy!Appointments. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

