CADENCE Remix this plan
Version 1.0 Module · Scheduling 2026-06-09

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.

01 · The thesis

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.

02 · Scope

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 .ics attachment
  • 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
03 · Architectural choices

Three decisions everything else hangs off.

These are locked before code. Each one shapes the data model, the API, or the test strategy.

CHOICE 01

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.

CHOICE 02

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.

CHOICE 03

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.

04 · The data model

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.

Entity-relationship diagram of the Cadence schema: User owns EventType, AvailabilityRule, CalendarConnection, and ApiKey; EventType generates Booking; Booking has Attendees.
FIG 1 · The Cadence schema. The booking race guard is a partial unique index on (event_type_id, start_at), not shown as a column.
05 · The slot pipeline

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.

Left-to-right pipeline: availability rules, subtract existing bookings, subtract calendar busy, apply buffers and minimum notice, normalize across DST, bookable slots.
FIG 2 · The slot pipeline. DST normalization is last so every earlier step works in wall-clock time.
06 · The booking flow

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.

Sequence diagram of the booking POST: guest to API, API re-validates against Postgres, checks Google Calendar freebusy, inserts the booking, creates the calendar event and Meet link, returns 201, then awaits the confirmation email.
FIG 3 · The booking sequence. The email send is the last step and is awaited, never fire-and-forget.
07 · Booking lifecycle

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.

State diagram: Pending to Confirmed, Confirmed to Rescheduled and back, Confirmed to Cancelled, Confirmed to Completed.
FIG 4 · The booking state machine. Every transition has a single trigger; there are no silent flips.
08 · Auth & API surface

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.

#EndpointWho calls it
01GET /slotsPublic · web page and CLI
02POST /bookingsPublic · web page and CLI
03PATCH /bookings/:id (reschedule)Public · token in link
04DELETE /bookings/:id (cancel)Public · token in link
05/event-types, /availabilityHost 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.

09 · Phasing

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.

Phase A

Schema & auth

The seven tables, migrations, host session, and the API-key flow. Make it boot.

Phase B

Event types & availability

CRUD for event types and weekly rules, timezone-aware, behind the host session.

Phase C

The slot engine

The pure slot pipeline and GET /slots, with DST and buffer tests.

Phase D

Booking, calendar, email

The booking POST, the race guard, Google sync, and the awaited confirmation email.

Phase E

Companion CLI & E2E

A CLI over the same API, plus a CLI-driven end-to-end run against a deployed instance.

10 · Open questions

Decisions we are flagging, not guessing.

Each of these is left for a human call rather than improvised mid-build.

#QuestionRecommendation
01What happens to a confirmed booking if the host deletes the event type?Keep the booking, soft-archive the event type. Existing commitments survive.
02Double-booking window when calendar sync lags.Trust the DB unique index as the final guard; treat calendar busy as advisory.
03Guest timezone: detect or ask?Detect from the browser, always show the timezone, let the guest override.
11 · Colophon

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".