A meeting scheduler, end to end.
Cadence is a Calendly-style scheduler: event types, an availability engine, two-way calendar sync, and a booking API a CLI can drive. This is the implementation plan, design and phasing locked before a line of code is written.
What Cadence does, who uses it, and why it matters.
A host publishes one or more event types (a 30-minute intro, a 60-minute
review) on a public link. A guest opens the link, sees only slots that are genuinely free,
and books one. Cadence writes the event to the host's calendar, attaches a video link, and
emails both sides an .ics invite. Reschedules and cancellations flow through
the same machinery.
The hard part is never the form. It is computing a correct slot: availability minus existing bookings minus whatever the host's real calendar already holds, with buffers, minimum notice, and daylight-saving boundaries all respected, and a race guard so two guests can never grab the same slot. Get that right and everything else is plumbing.
What ships in V1.0, and what deliberately waits.
A tight first version. Everything in the left column is load-bearing for a real booking; everything on the right is a clear V1.1 candidate we are choosing not to block on.
In · shipped in V1.0
- Event types with duration, buffers, and minimum notice
- Weekly availability rules per host, timezone-aware
- Public booking page driven by a slot API
- Google Calendar two-way sync (freebusy + event create) with a video link
- Email confirmation with an
.icsattachment - Reschedule and cancel, both reflected on the calendar
- A companion CLI that books through the same public API
Out · deferred to later
- Paid bookings and Stripe checkout
- Round-robin and collective (multi-host) events
- Outlook / iCloud calendar providers
- Workflows (reminders, follow-ups, no-show tracking)
- Team pages and routing forms
- Analytics dashboard
Three decisions everything else hangs off.
These are locked before code. Each one shapes the data model, the API, or the test strategy.
One API, two front doors.
The web booking page and the companion CLI both call the same public endpoints.
Nothing is forked, nothing mocked. The CLI is not a second implementation of booking logic;
it is a thin client over POST /bookings and GET /slots. That makes a
CLI booking a real booking, which is what turns the CLI into a genuine end-to-end test harness
later.
Slots are computed, never stored.
We never persist a table of "available slots". Availability is derived on every request from rules minus bookings minus calendar busy time. Storing slots would mean invalidating them every time the host's calendar changes, which is a cache-coherence problem we refuse to own. The slot pipeline (§05) is pure and re-runnable.
The race guard lives in the database.
Two guests can open the same slot at the same instant. The guarantee that only one wins is a
partial unique index on (event_type_id, start_at) for non-cancelled bookings, not
application code. The insert either succeeds or violates the constraint; there is no window in
between. Application-level checks are an optimization on top, never the source of truth.
Seven tables, agreed before the first migration.
A host owns event types, availability rules, and calendar connections. Event types generate bookings; each booking has one or more attendees. API keys hang off the host for CLI access. This is the whole schema, drawn as an entity diagram so a missing relation is visible at a glance.
(event_type_id, start_at), not shown as a column.How a free slot is computed, every request.
A pure function, left to right: start from the host's availability rules, subtract bookings we already hold, subtract the busy blocks the calendar reports, apply buffers and minimum notice, then normalize across daylight-saving boundaries before returning bookable slots. No step writes anything; the whole pipeline can run a thousand times with no side effects.
What happens when someone clicks "book".
The booking POST re-validates the slot, double-checks the host's live freebusy, inserts under the race-guarding unique index, creates the calendar event with a video link, and only then returns. The confirmation email is awaited, not fired and forgotten, so it cannot be dropped when the function returns.
One booking, five states.
Every booking moves through an explicit state machine. Reschedule is not a delete-plus-create;
it is a transition that creates a fresh calendar event and returns to Confirmed.
Completed is reached only when end_at has passed. Modeling this as
states, rather than booleans, keeps the calendar and the database from ever disagreeing.
Public booking, authenticated management, one CLI key.
The booking surface is public and unauthenticated: a guest needs no account. Host management (event types, availability, connections) sits behind a session. The CLI authenticates with a single API key tied to the host. Three audiences, one back end.
| # | Endpoint | Who calls it |
|---|---|---|
| 01 | GET /slots | Public · web page and CLI |
| 02 | POST /bookings | Public · web page and CLI |
| 03 | PATCH /bookings/:id (reschedule) | Public · token in link |
| 04 | DELETE /bookings/:id (cancel) | Public · token in link |
| 05 | /event-types, /availability | Host session |
| 06 | /calendar/connect (OAuth) | Host session · interactive consent |
The one step that needs a human. Connecting a calendar is an OAuth consent screen, which an agent cannot click. So it is handled up front, before any autonomous build starts, and recorded as a prerequisite. Everything downstream of it runs unattended.
Five phases, each one shippable.
Each phase boots, passes its own checks, and stacks on the last. A sub-agent owns one phase end to end and opens a PR.
Schema & auth
The seven tables, migrations, host session, and the API-key flow. Make it boot.
Event types & availability
CRUD for event types and weekly rules, timezone-aware, behind the host session.
The slot engine
The pure slot pipeline and GET /slots, with DST and buffer tests.
Booking, calendar, email
The booking POST, the race guard, Google sync, and the awaited confirmation email.
Companion CLI & E2E
A CLI over the same API, plus a CLI-driven end-to-end run against a deployed instance.
Decisions we are flagging, not guessing.
Each of these is left for a human call rather than improvised mid-build.
| # | Question | Recommendation |
|---|---|---|
| 01 | What happens to a confirmed booking if the host deletes the event type? | Keep the booking, soft-archive the event type. Existing commitments survive. |
| 02 | Double-booking window when calendar sync lags. | Trust the DB unique index as the final guard; treat calendar busy as advisory. |
| 03 | Guest timezone: detect or ask? | Detect from the browser, always show the timezone, let the guest override. |
What this plan is, and is not.
This is a demonstration plan: a realistic, self-contained scheduler spec packaged in the same shape every Cadence-style plan ships in, an editorial article, the canonical plan, and a live roadmap. It is deliberately generic so anyone can remix it as a starting point for their own build.
It is not a product announcement and not the only way to build a scheduler. It is an example of a plan an agent can read once and execute in phases, unattended, from "nothing exists" to "shipped".