Build with AI

How to build a team meeting scheduler with Claude Code

Stop paying for every person on the booking page. Describe your team, their hours and your meeting types in plain words, and Claude Code writes the slot engine, the booking write the database refuses to duplicate, and the Google Calendar connection that keeps its tokens on the server.

September 2026 · 57 min read

Claude Code

$ Build a team meeting scheduler: meeting types with a length and a location, free times worked out on the server from each host’s weekly hours in their own time zone, round robin and collective meetings, group sessions with seats, one booking write the database protects from double booking, a manage link for the guest, and Google Calendar sync.

  • Availability computed and proven
  • Booking write and team rules wired up
  • Ready for you to review
You describe it, Claude Code builds it
Start here

What a team meeting scheduler actually is

A shared diary with a front door. It has to know who can take each kind of meeting, when each of them works in their own time zone, what their calendar already holds, and who else is booking right now, and be right about all four when a stranger picks a time.

Most small applications store what people type and give it back later. A scheduler is different, and the difference shapes every decision below: what it offers is somebody’s time, each slot exists once per person, and the answer to “is Thursday at ten free” depends on a calendar the app does not own and can change while the visitor is looking at the page.

It is also why most readers arrive already renting one, and paying for it by the head. The rate per person is modest on its own. What a growing team meets later is that the features which make it a team tool, handing bookings round and meetings that need two people at once, often sit a plan above the one they started on, so hiring and growing are both line items.

What makes it hard to build is not the grid of times. The grid is a conclusion: each host’s weekly hours in their own zone, minus their days off, minus the gaps around meetings they already have, minus anything inside your notice period, minus what their Google Calendar says, and then, for a team meeting, combined across hosts. That conclusion has to hold when two people act on it in the same second.

Hours belong to people, not to the business

A company-wide nine to five works until the first host lives somewhere else. Weekly hours are stored per person, in that person’s time zone, and turned into real moments for each date, so a Friday in London and a Friday in New York are two different sets of hours that happen to share a name.

The meeting type decides who is asked

One-on-one asks one host. Round robin asks every host in the rotation and picks one when the booking arrives. Collective asks every host and offers only the times they all share. A group session asks one host and counts seats. The visitor sees the same page each time, with four different questions underneath it.

The other calendar is the one people trust

Your hosts live in Google Calendar, not in your app. A dentist appointment added there this morning has to block the slot on your page this afternoon, and a booking made on your page has to appear there with its video link. Both directions fail quietly when they fail, so both deserve a test of their own.

Why time zones come first

Nearly a third

of meetings now span more than one time zone, up 35% since 2021, according to Microsoft’s June 2025 analysis of anonymised Microsoft 365 activity. That is measured across large organisations rather than small teams, but the shape travels: the moment one host or one client is somewhere else, a scheduler that thinks in a single zone is showing somebody the wrong hour.

Microsoft WorkLab, Work Trend Index special report, June 2025 · checked published June 2025

What a scheduler needs

The parts every team scheduler is built from

One of these six is the product and the other five are built around it. If you read only one, read the first: it is where the build time goes and where the embarrassing failures come from.

01

Free times worked out from each host’s own rules

For each date, take the host’s weekly hours in their own time zone, drop the dates they marked off, cut what remains into start times at the interval you chose, then remove anything inside your notice period, anything that would run into one of their existing meetings once the gaps before and after are added, anything their Google Calendar marks busy, and any day where they have already reached the limit you set. What survives is what you may offer. Every one of those inputs lives on the server, so the answer does too, and the browser is told rather than asked.

02

A meeting type is a set of rules, not a name

A 15-minute intro call and a 90-minute workshop want different notice, different gaps either side, a different daily limit and different questions in the form. Put those rules on the meeting type rather than in one global setting, along with where the meeting happens, and the same host’s Tuesday produces a different set of times for each.

03

One write that cannot double-book a host

Two visitors pick the same 10am with the same host, and both press the button within a second. The server has to work the times out again inside the write rather than trusting what either page was shown, and the database should refuse two confirmed meetings that overlap for the same person whatever the code above it gets wrong. With both in place there is nothing to hold and nothing to sweep up afterwards: the second booking is simply told the time has gone.

04

Round robin with a rule you can explain

When a booking could go to any of four hosts, something picks one, and sooner or later a host asks why the last three went to somebody else. Fewest recent bookings first, or a fixed order of priority, are both defensible. What matters is that the rule is written down, a host can be taken out of the rotation for a fortnight, and each booking records who got it.

05

A link that manages the booking without an account

A client will want to move the meeting or call it off, and will not make an account to do it. The confirmation carries a link that does both. It stands in for a password, so it is long and random and stored only as a hash, and moving the meeting should update the invitation already in their calendar rather than sending them a second one.

06

A booking page that goes where your clients are

Most bookings start somewhere other than your booking page: a pricing page, a proposal, a signature in an email. An embed that sits inline on your own site, opens as a popup from a button, or hangs off a text link puts the same page wherever the client already is, with your logo and colour rather than somebody else’s.

Build vs buy

Build it once or pay for every host

Scheduling tools price per person who can be booked, from $10 to $28 a user a month across the first three below. Count the hosts you expect next year, not this year, before choosing.

Build your own

An app you own has no meter on the team. Nobody counts your hosts, and round robin is a setting on the team page rather than a reason to change plan. With an AI coding tool writing the slot engine, the booking write and the access rules, that build is weeks rather than quarters.

  • The sixth host joins the rotation without anybody reopening the budget
  • Round robin, collective meetings and group sessions are parts of the app rather than parts of a pricing tier
  • Your booking page lives on your own domain and inside your own site, not on a vendor’s subdomain
  • Every booking, answer and cancellation reason sits in your own database, queryable without an export
  • How round robin chooses, how much notice you need and how long a gap to leave are your rules to write
  • The invitation a client receives carries your name and your reply-to address, and nobody else’s logo

Rent the scheduler

Calendly · Cal.com · SavvyCal · Chili Piper

What renting buys is years of scheduling machinery, and some of it is genuinely tedious to reproduce: sync with Outlook and iCloud as well as Google, deposits, packages and invoices, routing that hands a lead to your CRM, and a support team for the week a calendar stops syncing.

  • Working the day you sign up, with every calendar provider already connected and verified
  • Outlook, Microsoft 365 and iCloud calendars, where this template connects Google Calendar only
  • Deposits, packages, coupons and invoices, where this template takes the full price by card at booking
  • Texts through any provider you like, where this template sends them through Twilio only
  • CRM hand-offs and territory routing for a sales team, where deciding who takes the lead is the product
  • Every one of the four bills per person, so the price moves each time the team does
CalendlyStandard $10 and Teams $16 per seat/month billed yearly ($12 and $20 billed monthly), Enterprise from $15k/yr

The name most clients already recognise, and the clearest example of the tier gap: round robin and team scheduling are on Teams and Enterprise only, so the Standard seat does not cover a team that shares bookings. Free allows “One event type” and “One calendar connection”. Both positions of the billing toggle were read, and yearly billing saves 17% on Standard and 20% on Teams. Enterprise “Starts at $15k /yr” and at 50 seats.

calendly.com · checked September 2026

Cal.comFree for 1 user, then Teams $12 and Organizations $28 per user/month billed yearly

The closest match to this template. Its Teams plan lists “Round-robin scheduling”, “Managed & collective event types” and “Routing forms”, with a 14-day trial. Free is genuinely free for one person, with unlimited event types and calendars, so the meter starts the day a second person joins. The page prints yearly figures only and advertises a 25% saving on them, so the month-to-month rate is higher than the one quoted here, and we have not guessed at it.

cal.com · checked September 2026

SavvyCalBasic $10 and Premium $17 per user/month billed annually ($12 and $20 billed monthly)

Included because it removes the tier argument and leaves only the meter: Basic already carries “Team scheduling”, “Round Robin Mode” and “Group Mode”, so a team pays the entry rate for every person and nothing more. Custom domains and paid bookings are on Premium. There is no free plan, only a trial and a “30-day money back guarantee”. Both billing positions were read, and paying annually saves two months.

savvycal.com · checked September 2026

Chili PiperRouting & Scheduling from $1,250/month billed annually ($15,000/year) for up to 15 seats, then $45 per seat/month

The other end of the market, where sending a lead to the right salesperson is the product rather than a feature. The entry plan includes “Up to 15 seats”, with “$45/seat/mo after that”, and the FAQ is plain about terms: “Monthly billing is not available at this time.” It is here to show what the category charges when distribution is the whole point. If that is your problem, the round robin in this template is a starting place rather than a replacement.

chilipiper.com · checked September 2026

Rule of thumb: if your hosts live in Outlook, your sessions are sold as packages or with deposits, or your leads have to reach a CRM the moment they book, rent. Those are real products, and none of the three is a weekend of describing. If what you need is one page for the team, bookings that reach the right person, and a bill that stays put when you hire, that is the half worth owning. One figure worth weighing either way, with its source in view: in a survey Calendly commissioned in mid-2024 of 1,244 workers in the US and UK, 43% said they spend at least three hours a week just scheduling meetings, up from 36% the year before. A scheduling vendor has an interest in that number, and it still describes a week most readers will recognise.

No dev needed

Why build with Claude Code

Most software looks simple from the outside, but it’s mostly hidden plumbing: a database, logins, permissions, validating forms, and dozens of screens that read and write records. Building all of that yourself means being fluent across the full stack, so weeks go to parts customers never see before the first real feature works.

Claude Code removes that barrier. The whole workflow becomes a simple loop:

The build loop
1

Describe

Say what you want in plain words in any language.

2

Build

It writes and edits real code across backend, auth, and UI.

3

Check

Run the app and see the change actually work.

Repeat

Ask for the next thing. Repeat.

Loop back to Describe

No stage of that loop asks for the full-stack expertise or the months of boilerplate that stop most people, which is why one person can ship a working app in a couple of weeks.

Three hard partshandled for you

The data model, authentication, and access rules are what make software like this genuinely hard to build by hand. Describe them and Claude Code scaffolds all three. After that, the rest is mostly screens on top.

Any language is the interface

No code to write, and no English required either. Whether you need a new field, a renamed step, or an AI summary, describe it in whatever language you think in and Claude Code handles the implementation.

Whole project in context

It finds and reads the files a change touches, instead of needing you to paste them in, so each edit stays consistent with what is already there. Point it at the two or three files that matter and it stays fast.

What it costs

Pay a developer, or do it with AI

Commercial schedulers bill for every person on the booking page. Count the hosts you expect to have in two years, because that headcount is the line that drives your bill.

Hire a developer

Custom build, from scratch
Developer
~$12k-$46k
Supabase (backend)
Free tier · $25/mo (Pro plan)*
Hosting
$0 free tier
Build time
~230 hrs of their work

~$12k-$46k to build, then from $25/mo after launch

Our ~230-hour estimate at market rates. The survey linked below puts senior US developers at $100-$150+ an hour and records agencies charging 20-40% above the freelancers they compete with, which is what makes $50/hr and $200/hr the honest ends of the range. Most of those hours sit where no screenshot shows them: the slot engine across hosts and time zones, the write that refuses a double booking, and the Google connection with its tokens kept on the server. That is the usual reason a quote for “a booking page” comes back at several times what the mockups suggest.

Build it with Claude Code

From scratch, with Claude Code
Claude Code
$20/month (Pro) to $200/month (Max)
Backend (Supabase)
Free tier · $25/month (Pro plan)*
Hosting
$0 on a free tier
Your time
~110 hrs

~$20-$200/month while you build, then whichever plan you keep using

Claude Code itself is free. The cost sits in the Claude plan behind it. The fee doesn’t shrink when you start from a template the way a per-hour developer bill would: Pro, at $20/month, covers a template import or a short build, and a from-scratch build that runs for weeks tends to need the $100-$200/month Max plan instead, because it outlasts Pro’s usage window. Either way, the template changes how many of the hours in the estimator above you actually spend, not which Claude plan you’re paying for.

* The free-tier line that matters here is the pause, not a storage number. Free gives you a 500 MB database, 1 GB of file storage and 5 GB of egress a month, and bookings are small enough that only your logo and cover image ever touch the storage figure. The pause is different: a free project stops after a week with no activity, and a booking page that has gone to sleep is a team that looks unavailable. From $25/mo, Pro removes the pause, raises egress to 250 GB (then $0.09 per GB), and keeps a daily backup for 7 days.

Neither column above grows with the team. The tenth host costs what the second one did, so after launch the only line that can move is an AI model you choose to call, and only if you add a feature that uses one.

Prices and rates from supabase.com, developex.com and claude.com, checked September 2026.

Plan first

Decide before you build

Six things to settle in writing first. Each one is a promise to somebody who is about to arrange their day around your team, and each costs far less to decide now than to unpick once real meetings are in the calendar.

01

Whose hours a time comes from

Decide whether availability belongs to the business or to each person. One set of opening hours is simpler, and wrong the moment a host works different days. Weekly hours per person, each in that person’s own time zone, cost a little more to build and are the only version that survives a second office.

02

How round robin chooses

Fewest recent bookings first, a fixed order of priority, or both? Write the rule in one sentence before anything is built, because hosts will ask why the last three meetings went to somebody else. Whatever you choose, record who got each booking, so the answer is a query rather than an argument.

03

What happens when Google does not answer

Your page asks each host’s calendar before offering a time. When that call fails, you either stop offering times or offer ones Google could not confirm. Offering them keeps the page working and risks an occasional clash. Stopping is safer and looks broken. Choose deliberately, and log the failures either way.

04

How much notice, and how many a day

Minimum notice stops a booking landing ten minutes from now. A daily limit stops a host doing eight calls on one Tuesday. A gap before and after keeps them from running late. Set all three per meeting type, since a quick intro call and a two-hour workshop want very different ones.

05

Whose clock the invitation is in

Store every meeting as one absolute moment, draw it in the viewer’s zone, and let the visitor correct the zone the page guessed. Then test the awkward cases on purpose: a client six hours away, a host in another country, and the week one of them changes the clocks and the other does not.

06

What a guest can change without an account

Guests will want to move or cancel. Give them a link that does both, and decide how late is too late. That link stands in for a password, so it should be long, random and stored only as a hash, and a reschedule should update the original invitation instead of sending a second one.

Approaches

Comparing your build options

One question in this app is worth more than every screen in it: is this person free at this moment. Three routes to the same product: by hand, on a UI kit whose calendar knows nothing about anybody’s hours, or through Claude Code end to end.

~230 hrsBuilding by hand

The screens are the quick part. The slow part is the question behind every time on the page: is this person free, given their hours in their own time zone, the gap you want after their last call, the notice you asked for, what their Google Calendar says, and whoever else is pressing the same button this second. Round robin asks it once per host, and a collective meeting asks it of everyone at once.

~170 hrsGeneric UI starter kit

A starter kit gives you a month grid, a form and a dashboard shell, which looks like most of a scheduler and is the part you would have finished anyway. Nothing in it knows whose hours apply, which host is next in the rotation, or that the 3pm on screen went to somebody else a minute ago. All of that is still yours to write.

~110 hrsBuilt with Claude Code

Ask for one piece at a time and the migration, the slot engine and the page reading it arrive together as a single change. Same task list as the rows above it, worked through by an agent that reads the surrounding code before it edits any of it, and that will print the working for one real day when you ask.

Interactive calculator

Estimate your exact build timeframe

Not every team needs all six features. Untick what yours can do without, like charging for a session or syncing with Google Calendar, to see your real build time.

What your scheduler needs

Your estimate

110 hrs

start to finish

Based on the 6 of 6 features you’ve selected, plus ~21h of groundwork. Toggle any on the left to watch the number move, and open the groundwork row to untick what you have already, such as a database that is already running or going live if you are only building a mock-up for now.

A rough estimate, not a quote. Real time depends on how much you customize and how clean your data is.

Setting up your workspace

Let’s set up the tools you need

Four things need to be on your machine before step 01, and none of it takes more than about 15 minutes. Three are ordinary installers you click through, and the fourth is an active Claude subscription. From there, you build simply by describing what you want, in your own words.

1

Claude Code

Cost: Free to install · needs a paid plan to build with

Your main AI assistant. Download and run the free Claude Code CLI, connect your Anthropic account or pay-as-you-go API key, and build your app in plain English. It runs in the Terminal, and if a command line puts you off, the same tool ships as a desktop app with buttons and windows.

Install Claude Code
2

Claude subscription

Cost: $20/month (Pro) or from $100/month (Max)

Claude Code itself is free, but the free Claude.ai plan does not include Claude Code access at all, so you need at least Pro, unless you pay as you go through a Console account instead. Pro at $20/month is enough to start with, though a long, from-scratch build tends to outrun what Pro allows in a given stretch, which is when people move up to Max, from $100/month. Every plan’s usage resets on a rolling window, so on a heavy day you may hit a limit and have to wait it out.

Compare Claude plans
3

Node.js engine

Cost: Free

The engine that runs your app on your own computer. You never have to learn how it works: download the version marked LTS (the most stable one), install it, and forget about it.

Download Node.js (LTS)
4

Supabase (database)

Cost: Free to start

Where your project keeps its data. Install it, then sign in once by running supabase login. Words like migrations and row-level security turn up later in the guide, and Claude Code writes those parts for you.

Install Supabase CLI

Nothing here is worth memorizing. These four just need to exist on your machine. From step 01 on, you say what you want and Claude Code runs the commands.

Step by step

Build your scheduler, prompt by prompt

You write no code at all: you say what you want, and Claude Code runs the commands. Pay attention to the order, because it is unusual. Availability is built and tested for every kind of meeting before a single booking exists and before anybody can sign in. Everything after it is a way of acting on an answer that has to be right first.

  1. 01

    Get it running, then write the two rules down

    An app booting against your own database, and a CLAUDE.md carrying the two constraints every later step leans on.

    PromptSet up the project
    Set up a new React 18 + Vite + TypeScript project with Tailwind and the Supabase JS client. Read VITE_SUPABASE_URL and the publishable key (the sb_publishable_… key, which replaces the older anon key) from .env, and add .env to .gitignore in the same step so neither value reaches GitHub. Add a typed Supabase client under src/lib, then write a short CLAUDE.md describing the stack and fixing the vocabulary for a team meeting scheduler (member, host, weekly hours, date off, meeting type, one-on-one, group, round robin, collective, slot, booking, manage link) and recording two standing rules. First: whether a time is free is always worked out on the server from each host’s own rules and existing bookings, and worked out again inside the write that creates a booking, never taken from what the browser was shown. Second: every instant is stored in UTC, each host’s weekly hours are kept in that host’s own time zone, and the browser only ever converts for display.

    Put both rules in the file, not only in this message. Everything after this assumes them, and a time zone handled “just in the browser for now” is the shortcut any assistant will reach for the first time a page needs to show a Friday.

  2. 02

    Model the team and the meeting types, then a page over them

    Hosts with their own hours, meeting types with their own rules, and the public booking page reading them. No bookings and no accounts yet, which makes this the cheap moment to find out your meeting types are organised the wrong way.

    PromptModel the team and build the booking page
    Write the data model as Supabase migrations, with no authentication yet. Members: name, email, title, a colour, a role of admin or host, their own time zone, a round robin priority, and whether they are in the rotation. Weekly hours per member per weekday, as one or more ranges in that member’s own zone, and dates off per member. Meeting types: name, URL slug, description, length in minutes, a kind of one-on-one, group, round robin or collective, seats for a group, a round robin rule of balance or priority, a location (Google Meet, Zoom, Teams, phone or in person, with a detail field), minutes of gap before and after, minimum notice, the interval between start times, a daily limit, and which members host it. Questions per meeting type, with a label, a type, options and whether it is required. One workspace row for the business name, accent colour, logo and default time zone. Seed three hosts in two time zones, one meeting type of each kind, and one host who is off on Fridays. Then build the public side: a page listing the meeting types, and a page per type with a month calendar, the start times for the chosen day as placeholders, and a time-zone picker that guesses the visitor’s zone.

    Seed the two time zones and the Friday off on purpose. Two hosts in London and one in New York is what proves the next step is computing times per person rather than drawing one grid, and inventing them now is easier than remembering you need them later.

  3. 03

    Work out availability, per host and then for the team

    The step this application is made of. Ask for it as a server-side calculation that combines hosts by the kind of meeting, then make Claude Code show you its working for one day rather than a screenshot of a calendar.

    PromptWork out availability properly
    Build availability as pure TypeScript shared with a server function, not in the browser. Given a meeting type and a date range of at most 45 days, return the start times that are genuinely free. For each host and each date: take that host’s weekly hours for the weekday in the host’s own zone and turn them into UTC moments for that date, drop the date if they marked it off, cut the hours into starts at the meeting type’s interval, then remove any start inside the minimum notice, any whose meeting plus the gaps before and after would overlap one of that host’s confirmed bookings, and every start on a day where the host has reached the daily limit. Then combine by kind. One-on-one and group use their one host. Round robin offers a start if any host in the rotation has it. Collective offers it only if every host has it. For a group, a start already booked stays on offer until its seats are full, and other starts overlapping it are removed. Write unit tests for each rule and for a day when the clocks change. Then print the working for one Wednesday for the round robin type, listing each host’s starts and which rule removed each missing one, and show the same week as a visitor in Tokyo would see it.

    Ask for the working, not just the calendar. A grid of times looks correct whatever produced it, and the order of those subtractions is where every double booking and every missing Friday in this category comes from. Reading them once, in order, for one real day is the cheapest review you will do on this build.

  4. 04

    Take the booking in one write the database protects

    The first step that writes anything: the booking itself, the link that lets a guest move or cancel it, and the email that tells them it happened.

    PromptTake the booking in one protected write
    Build the booking write as one Postgres function called by a server function, never as separate inserts from the browser. It takes the meeting type, the start, and the guest’s name, email, time zone and answers. Inside one transaction: take an advisory lock per host involved, work the start out again with the same rules as step 03, pick the host for round robin (balance means fewest confirmed bookings from seven days ago to thirty days ahead with priority breaking ties, priority means the highest-priority host who is free), check seats for a group and the daily limit, then insert the booking and a row per host. Add an exclusion constraint so two confirmed rows for the same host with overlapping times can never exist. Generate 32 random bytes as a manage token, store only its SHA-256 hash, and build a manage page where the guest can cancel with a reason or pick a new time, keeping the same calendar invitation id with its sequence increased. Send a confirmation, a reschedule notice and a cancellation through Resend with an .ics attached, and log and skip the email when no key is set. Reject any submission that fills a hidden honeypot field. Then prove the race: fire two bookings for the same host and start at the same moment, and show one of them refused.

    Insist on that last demonstration as running code rather than an explanation. Two people pressing the same 10am is the failure a client experiences as your team being disorganised, and it is invisible in every test you run on your own.

  5. 05

    Sign-in, two roles, and nothing at all for anonymous visitors

    The database now holds the names, emails and answers of real clients. Two kinds of account share it, and the visitor with no account should reach none of it directly.

    PromptAdd auth, roles, and access rules
    Add Supabase Auth with email and password, a password reset, and linking an account to its member row by email, ignoring case. The first account on an empty project becomes the admin, under a lock so two sign-ups at once cannot both become admin, and a later sign-up whose email is not a member gets no access at all. Keep the role on the member row and add a trigger that refuses changes to role, active, email, priority or the rotation flag unless an admin is asking, plus one that refuses to remove the last admin. Then enable row-level security on every table with no policy for anonymous visitors at all: the public page keeps reading through the server functions from steps 03 and 04, which return only what a booking page should show. A host reads the bookings they are on and edits their own hours and dates off. An admin reaches everything. The branding bucket is public to read, admin-only to write, and refuses SVG. Then prove four things by querying as a signed-in host: another host’s booking comes back empty, an anonymous request to the bookings table returns nothing, a host cannot make themselves admin, and the last admin cannot be demoted.

    The anonymous case is the one to check hardest. The tempting shortcut is a policy that lets anybody read the meeting types and hours so the booking page can query them directly, and it passes every test you will think of while publishing your team’s whole schedule to anyone who opens the network tab.

  6. 06
    Destination

    Google Calendar, the back office, the embed, and a rehearsed week

    The calendar your hosts actually live in, the screens your team works from, the snippet that puts the page on your own site, and then the part most builds skip: use the scheduler as five different people.

    PromptConnect Google, add the back office, and rehearse
    Finish the app. Google Calendar first: an OAuth connection per host asking only for calendar.events and calendar.freebusy, a signed state on the callback, the refresh token stored in Supabase Vault and read only by server functions, and busy times from free/busy removed from the starts in step 03 (if Google errors, offer the times anyway and log it). Write each booking as an event on the first connected host’s calendar with the guest and any other hosts invited, add a Meet link when the location is Google Meet, and delete the event on cancellation. Then the back office: bookings by week, month and list with a host cancel, the meeting type editor with details, limits, questions and hosts, each host’s hours and dates off, the team with invites and round robin settings, analytics over 7, 30 or 90 days, branding, and a share page that writes the embed snippet as inline, a popup button or a popup text link, with the iframe resizing itself. Then rehearse a week: book each kind of meeting as a stranger, book the round robin type five times and check who got them, cancel and reschedule from the email link, add a busy event in Google and watch the time disappear, and embed the page on a test site.

    Do the rehearsal in separate browser profiles rather than switching your own role, and put a real event in a host’s Google Calendar before you check the page. A calendar connection that saves its token and then never reads busy time looks exactly like one that works until the first client books over a dentist appointment.

Authentication & security

Protect the team calendar and your clients

A booking says who is meeting whom, when, and often why, in the answers to your questions. What follows are the database rules and server-side checks that keep each record with the people it belongs to.

Standard Password Protection

Sign-up, sign-in, sessions and password resets belong to the auth service that ships with your database. Only your team signs in, since clients book without an account. One detail matters on day one: the template makes the first account on a fresh project the admin, so create yours before the address goes anywhere. A later sign-up whose email is not on the team gets no access at all.

Separate Admin and Host Access

Two roles cover a team. An admin manages the meeting types, the team, the branding and every booking. A host manages their own hours and calendar and sees the bookings they are on. The case worth thinking about is the visitor with no account, who in this template has no table access at all: the public page reads what it needs through server functions that return only what a booking page should show.

Automatic Double-Booking Protection

If the page posts “this time is free” along with the booking, the way to take a time that is not free is to change what the page posts. The server works the times out again at the moment of the write and takes a lock per host, and the database itself refuses two confirmed meetings that overlap for the same person, so a race is lost at the constraint rather than discovered on the day.

Data Rules Protected from Tampering

A list of bookings narrowed in a component is one forgotten condition away from showing a stranger who your team is meeting and what they wrote in the form. Row-level security asks that question inside the database instead, as the rows are handed over. The reason to move it there is what happens on the day somebody forgets: the query comes back empty rather than with the whole calendar.

Strict Privacy for Guest Details

The template’s migrations declare 36 row-level security policies, which is a modest number for a reason: anonymous visitors are given none, so every policy decides which member of your team sees what. Take the bookings table. An admin sees every booking, a host sees the ones they are on, and a guest reaches theirs only through a server function that returns that one booking and nothing beside it.

Private & Secure Booking Links

Letting a guest move or cancel without an account means something in the link stands in for a password. The template generates 32 random bytes for each booking, sends them in the confirmation, and stores only their SHA-256 hash, so a copy of the database is not a copy of anybody’s link. A booking number in a URL would be a page anybody could walk through by changing a digit.

Bot & Brute-Force Protection

The public booking form is the one endpoint a stranger can call as often as they like. The template rejects any submission that fills in a hidden field real visitors never see, which stops the laziest bots, and that is the whole of its protection: there is no rate limit on it. If your page gets real attention, ask your AI coding tool to add one keyed by address and kept somewhere shared, not in one function’s memory.

Prevent Unauthorized Admin Escalation

A role stored on a record its owner can edit is a role anybody can give themselves. The template keeps each person’s role on the team table and has a trigger refuse any change to it, or to their round robin settings, unless an admin is asking, and a second trigger refuses to remove the last admin. That matters here because an admin reads every client’s name, email and answers.

Privileged Actions Run Server-Side

Working out free times, writing a booking, handing it to a round robin host, taking a payment, connecting a calendar and sending the invitation or a reminder each need to do more than the person who set them off may do directly. The template gives this work 14 server functions, each checking who is asking inside its own code, and the key they run with stays on the server, never in the app a visitor downloads.

Calendar Tokens Kept in a Vault

Connecting Google Calendar hands your app a refresh token that can read and write that host’s calendar until somebody revokes it. The template stores it encrypted in Supabase Vault, reachable only by the server functions through one narrow database function, and never returns it to the browser. Disconnecting revokes the token at Google as well as deleting your copy.

Guest Answers Treated as Personal Data

Booking questions invite people to write things down: why they want the call, a phone number, a company name. Decide who on the team may read them, how long you keep last year’s bookings, and what you do when somebody asks for theirs to be deleted, and remember that Google Calendar keeps its own copy of every event you write there.

Automatic Daily Data Backups

No backup is taken of your meeting types, your team or a single booking on the free tier. Daily backups, kept for a week, start on Supabase Pro at $25/mo. Worth having before the calendar is the only record of next month, because the invitations sitting in your clients’ inboxes will not rebuild your database for you.

PromptCheck who can see what
Review the access rules (row-level security policies) on every table. For each one, tell me in simple terms who can view, add, edit, and delete records, confirm that people can only reach their own data while the right roles can reach more, and flag anything left open that shouldn’t be.

Run this before launch to make sure nobody can see data they shouldn’t.

One rule outranks the rest here: the database service key, your Google client secret, the secret that signs a calendar connection, and any AI provider key live on the server and nowhere else: not in the app a visitor downloads, and not in a public repository. Treat any of them that escapes as burned, and replace it the same day.

Workflow rules

What speeds the build, and what slows it

Speeds the build

  • A CLAUDE.md notes file that spells out your setup and preferences
  • Asking for a plan first on anything that touches several files
  • One change per request, small enough to describe in a sentence
  • Pointing it at the two or three files that matter
  • Running the app and checking each change before the next
  • Saving a working version (a git commit) after each step, so you can undo

Slows the build

  • Vague prompts like “make it better”, which leave it guessing what you meant
  • Asking for a whole feature in one giant prompt
  • Dumping the entire project into the chat at once
  • Skipping the notes file, so it forgets your conventions each session
  • Accepting changes without running or reading them
  • No saved versions to roll back to when something breaks
Version control

Git: what it is, and why you need it

Before you build anything, meet the one tool that makes building safe. You need no coding background for it: Git remembers every version of your project, so you can try things, break things, and get back to a working state in seconds.

What Git actually is

Git is a quiet recorder that runs alongside your project. Each time you save your work it keeps a full snapshot, so the entire history of your project lives on your computer, not just whatever the files look like right now.

Why you need it

Claude Code runs inside a permission mode you choose, either asking before each change or working more freely once you trust it. Either way, experiments sometimes still break things. Git is what makes that safe: there’s always a working version to return to, so you can try bold changes without the fear of losing what already works.

A commit is a save point

Each commit is a snapshot with a short note, like “added the home page”. Make one after every working step and you can jump back to any of them later.

GitHub’s beginner guide to Git

Undo anything, safely

If a change breaks something, you roll back to the last good commit instead of unpicking it by hand. It’s the safety net that makes bold experiments with Claude Code low-risk.

GitHub is Git’s home online

Git lives on your computer. GitHub is a free, private cloud copy of the same project. It’s your backup if your laptop dies, and the place Claude Code can always get back to. Keep it private, and never commit secret keys or passwords.

Create a free GitHub account

You rarely type git commands

You do not have to memorize any of it. Ask Claude Code to “commit this” or “undo the last change” and it runs the git steps for you. Prefer clicking to typing? Claude Code’s own desktop app, which you install separately, shows each change side by side before you keep it, and GitHub Desktop gives you plain buttons for saving and rolling back.

Get the Claude Code desktop app
Going live

Where to host your application

Hosting gives your app a home on the internet so anyone can open it via a web link. Choose a service below to make your site live. (Your database, logins, and business records are stored separately in Supabase, covered below).

HostBest forNotesFree tier
VercelOne-click deploysPoint it at the repository once and each push publishes itself, with nothing for a Vite project to configure. Read the plan terms before a business domain goes near it: Hobby is licensed for personal, non-commercial use, and a booking page for a team that sells its time is commercial however small the team is, so Pro, at $20/user/mo.Pro from $20/user/mo (Hobby is non-commercial)
NetlifyDrag-and-drop or GitConnect the repository or drop the built folder onto the page, and you are live inside a minute. Add the one redirect rule it asks for: without it, a link straight to one meeting type, or the link in a client’s confirmation email, returns a not-found page.Free tier
Cloudflare PagesClients in other countriesCopies of the site sit close to whoever is loading it rather than in one place. Worth choosing if your clients book from abroad, which is also the situation that makes testing your time-zone handling properly unavoidable.Generous free tier
GitHub PagesNot really this appPublishes free out of your GitHub project once you change a routing setting. Here mainly to be ruled out: publishing free means the repository is public, and this code sits beside a database of who your team is meeting and what they wrote in the form.Free from a public repo only
Firebase HostingTeams already on GoogleConfigure it once and each release is a single command afterwards. The argument for it is that your calendars, your mail and the Google Cloud project behind the calendar connection are already Google ones.Free Spark tier
AWS Amplify HostingTeams already on AWSPublishes out of the AWS console, and takes the same one rewrite rule so a link to a single meeting type resolves. Pick it when AWS is already on the invoice and adding another supplier is the part you want to avoid.Free tier (build + hosting)
SurgePublish from the terminalA single command sends the built folder online, with no repository involved anywhere. Useful for showing a colleague how the booking page feels before you commit to it. Not for the link that goes in your email signature.Free - unlimited publishing
DigitalOcean App PlatformDigitalOcean usersBuilds and serves out of the account that already runs whatever else you have. One supplier and one invoice is the entire argument, and for a small team that is a real one.Free - 3 static sites, 1 GB/mo transfer

Any of them serves the app perfectly well, so judge them on three questions instead of on speed. Whether the plan allows commercial use, since Vercel’s Hobby tier does not. Whether it publishes from a private repository, because this code sits beside your clients’ details. And whether a deep link resolves in a browser that has never seen your site: a link to one meeting type and the manage link in a confirmation email both have to land on the right page rather than the home page.

Calendar connections that stop working after a week are Google’s Testing mode, not a bug. While your Google Cloud consent screen is set to Testing, only the accounts you list can connect, and Google expires their refresh tokens after 7 days, so every host has to reconnect weekly and the page quietly stops checking their calendar in between. Publishing the app removes that, and because the template asks to read and edit calendar events, Google asks for verification first. Start that before launch week, not during it.

Database & backend

Keep your data in Supabase

The team, the meeting types, each host’s hours, the bookings and your logo. This is also where the logic that has to outrank the person asking lives, and where each host’s calendar token is kept encrypted.

ServiceBest forNotesFree tier
SupabaseData, auth, functions, files, secretsThe team and the bookings sit in Postgres, accounts come from its auth service, your logo and cover image go into its storage, and its edge functions carry the work that has to be permitted more than the visitor setting it off: working out free times, writing the booking, talking to Google and sending the email. Getting there is opening a free project and giving the app two values, its URL and its publishable key. The calendar tokens go into its Vault, encrypted, where only those functions can reach them.Free tier, then usage-based
AI workflows

Where AI genuinely helps a team that takes meetings

Each of these is one more prompt once the scheduler is running, and each can be pasted in as written. They all reach the model through one server-side function, the only place your API key is kept.

Turn “any afternoon next week” into three real times

Plenty of meetings still start as an email that says roughly when somebody is free. Reading it, checking the team’s calendars and replying with options is the small daily tax this removes, and it never books anything without you.

PromptTurn “any afternoon next week” into three real times
Add a server-side ai function (one place, with my provider key only on it) and a screen where I paste a message from a client. Send the message to that function and get back a structured guess: which of my meeting types they seem to want, the window they are describing, and their time zone if the message gives one away. Then run that window through the real availability for that meeting type and show me the three closest free times as a draft reply I can copy, with a booking link for each. Never create a booking from the model’s output. Where the message is vague, say so rather than choosing for me: if it says “sometime next week”, I want to see that, not a Tuesday you picked.

A short brief before every meeting, from the answers in the form

Your booking questions already collect why somebody wants the call. A host reading three lines before it starts walks in prepared, and the model only ever sees what the client chose to write.

PromptA short brief before every meeting, from the answers in the form
Add a “prepare” action on a booking that sends the meeting type, the scheduled time and the answers to my booking questions to my ai function, and returns a three-line brief for the host: what the client wants, what to have ready, and one question worth asking. Send no email address, no phone number and no name. Show the brief on the booking in the dashboard only, never write it to Google Calendar or into an email, and say plainly when the answers are too thin to brief from rather than padding them out.

Draft the reply when a client asks for a time you do not offer

A request for a Saturday, a time outside anybody’s hours, a third reschedule in a week. The words are the work here, and keeping them consistent across the team is worth more than writing them fast.

PromptDraft the reply when a client asks for a time you do not offer
Add a “draft a reply” action that takes a client’s message and the meeting type it is about, and returns a short, polite reply I can edit before it goes anywhere. It may only offer times that the availability function actually returns, it must say when nothing fits rather than inventing an exception, and it never promises that a host will make time outside their hours, because that is a decision for the host and not for the model.

Find the pattern in a month of cancellations

The cancellation rate on the dashboard tells you how many. What you want to know is why: the same reason three times, always for the same meeting type, always booked more than a fortnight ahead.

PromptFind the pattern in a month of cancellations
Add a panel on the analytics page that groups the last period’s cancellation reasons by what they are actually about, using my ai function, and returns each theme with a count, one representative quote, and which meeting type and how far ahead the booking was made. Send the reason text only, with no names or email addresses. State counts as figures, print the period it covered beside the result, and where a theme rests on one or two cancellations, say so instead of presenting it as a trend.

Ask your own calendar whether round robin is fair

Round robin is supposed to share the work. Whether it does, once somebody has been off for a week and somebody else joined halfway through the month, is a question worth asking the data rather than the team.

PromptAsk your own calendar whether round robin is fair
Add a panel that answers questions about my own booking history through my ai function: bookings per host per week, how round robin meetings were shared out, cancellation rates by meeting type and by host, and which hours of the week fill first. Have it compute every figure with queries and use the model only to explain what they suggest, so no number is invented. Every answer states the period and the sample size, and where a pattern is thin it says the pattern is thin. Send no client names or contact details at all.

Each prompt above picks the model that fits the job. As a rule of thumb, that is Haiku for high volume, Sonnet for everyday writing, and Opus for deeper reasoning. Model names move faster than this page does, so check the current list in the Claude docs (linked in the references below) before you build. Send every one of these prompts through that same ai function, so one key and one set of rules governs all of them.

Ready-made option

Get a head start with our template

Every route above begins at an empty folder, which is not the only place a scheduler can begin. This one exists, runs, and takes bookings, so the weeks that the slot engine, the booking write and the calendar connection would have cost turn into an afternoon of adding your team and your hours.

Meeting Scheduler like Calendly

The exact scheduler this guide builds, packaged so you can open it, point it at your own backend, and make it yours from there. A scheduling app for teams that meet clients. People choose a time on your booking page or on your own website, answer your questions, pay by card when the session has a price, and get a calendar invitation by email and a reminder before the meeting. Round robin hands each booking to whoever is free, a collective meeting only offers times when every host can make it, and group sessions stay open until the seats run out.

React 18ViteTypeScriptTailwind CSSSupabase
Out of the box

The key benefits of starting with a template

The times on the page already come from each host’s own hours and calendar, and the database already refuses to give two people the same host at once. That is most of what this saves you. Behind it, the four meeting kinds, the manage link, the emails, the dashboard and the embed are done too.

Building the core from scratch

~110 hrs

Opening the template, already built

~1 hr

~109 hrs of building you skip

Two different measurements, on purpose. Building the application is the ~110 hrs, and that figure covers the six rows above, while the template also ships reminder workflows, a routing form and a contacts list that the calculator does not count. The ~1 hr is what adopting the built one costs: connect a database of your own, load the sample team or your own, and set your hours. Setting up a Google Cloud project for the calendar connection sits outside both figures.

Availability that already handles four kinds of meeting

A server-side slot engine works out free times from each host’s weekly hours in their own time zone, dates off, gaps before and after, minimum notice, the start-time interval and a daily limit, then combines hosts for round robin and collective meetings and counts seats for group sessions. It is shared code with unit tests of its own, so the rule you are most likely to change is the one with the best cover.

A booking write the database itself protects

Every booking is a single database call that takes a lock per host, works the times out again, and inserts under an exclusion constraint refusing two meetings that overlap for the same person. A free booking is confirmed in that one write. A paid one holds the time for 15 minutes while the client pays, and the scheduled job that sends reminders also frees any hold that ran out.

Two roles across 36 declared policies

Admin and host, with the role guarded by a trigger so nobody can promote themselves, and 36 row-level security policies of which none admits an anonymous visitor. Around them, 14 server functions for the work that has to outrank the person asking: the public page, free times, booking, payment and the Stripe webhook, managing a booking, a host’s cancellation, the routing form, the workflow runner, the invitation file, the calendar connection and team invites.

Google Calendar and email, both directions

Hosts connect Google Calendar, busy time is checked before any time is offered, and each booking is written to the host’s calendar with the client and any other hosts invited and a Meet link when the meeting is on Google Meet. Clients get a confirmation, a reschedule notice or a cancellation by email through Resend, each with an .ics attached and a link to manage the booking, and workflows add reminders and follow-ups by email or by text through Twilio.

A back office and a page that travels

Meeting types with an editor for details, limits, questions and hosts, a bookings calendar by week, month or list, each host’s hours and dates off, the team and round robin settings, analytics over 7, 30 or 90 days, branding with your logo, colour and layout, and an embed for your own site inline, as a popup or behind a text link. A sample team loads in one click so there is something to look at on day one.

Got questions?

Common questions

Google Calendar, and only Google Calendar. Each host connects their own account, their busy time is checked before a time is offered, and new bookings are written back with the client invited. Outlook, Microsoft 365, iCloud and CalDAV calendars are not included. Adding Microsoft is a described change rather than a rebuild, but it brings its own sign-in, its own tokens and its own verification with Microsoft, so plan it as a project of its own.

Yes. Workflows send an email or a text at a time you choose: when a meeting is booked, a set time before it starts, a set time after it ends, on a no-show or on a cancellation, with the client’s name, the time and the manage link filled in. One scheduled job runs them every five minutes, and you switch it on with a short SQL snippet from the setup guide. Emails go through Resend and texts through Twilio. Without those keys the messages are logged instead of sent and bookings still work, which is useful while you build and a surprise if you forget it at launch.

Yes, through Stripe. Give a meeting type a price and the client pays by card on the booking page while the time is held for them for 15 minutes. A cancellation by the host is refunded in full, and so is one by the client made before the refund window you set (24 hours unless you change it). Payment covers the full price at booking only, so deposits, packages, coupons and invoices are additions. Without Stripe keys a paid meeting is still booked, with the payment due at the appointment.

Three things, in order. Free times are worked out on the server from each host’s rules and their existing meetings, so a taken time is never offered. The booking is written by one database call that takes a lock per host and works the times out again inside it, so a time that went while somebody was typing is refused. And the database carries a constraint refusing two confirmed meetings that overlap for the same host. The check worth asking your AI tool to demonstrate is the race: two bookings for the same time at the same moment, and one of them refused.

By one of two rules you choose per meeting type. Balance gives it to whoever has the fewest confirmed bookings from seven days ago to thirty days ahead, and uses priority to break a tie. Priority gives it to the highest-priority host who is free. Either way the page offers a time if any host in the rotation is free then, and a host can be taken out of the rotation without being removed from the team. The booking records who got it, so a question about fairness is a query.

A collective meeting needs every host on it, so the page offers only the times they all share, and every one of them is attached to the booking. A group session has one host and a number of seats: the same start time stays on offer until the seats are taken, and while it is running that host cannot be booked for anything else that overlaps it. Both are settings on the meeting type rather than separate features.

Every meeting is stored as one absolute moment. Each host’s weekly hours are kept in that host’s own zone, and the booking page guesses the visitor’s zone and lets them change it. That is the right shape, and it still needs testing: book a meeting with your computer set to another zone and check the time in the invitation, and do it again in the weeks when Europe and the US change their clocks on different dates.

Yes. One script tag gives you three ways to show it: inline in the page, as a popup opened by a floating button, or as a popup behind any text link you choose. The embedded page resizes itself to fit, so it does not sit in a scrolling box inside your site. The share page in the dashboard writes the snippet for each meeting type, so there is nothing to assemble by hand.

Only for the calendar connection, and yes, it has to be your own. You create a Google Cloud project, an OAuth client and a consent screen, and give the server functions the client’s ID and secret. While the consent screen is in Testing, only listed accounts can connect and their tokens expire after seven days, and publishing it means going through Google’s verification, because the app reads and edits calendar events. Everything else in the scheduler works without it.

No, and this is the half an AI coding tool handles best. Describe the behaviour you want in ordinary language and back come the tables, the accounts, the rules deciding which host sees which booking, the function turning each host’s hours into free times, the booking write the database protects, and the calendar connection. Your share of it is opening a free Supabase project for all of that to be written into.

Somewhere to keep the data and somewhere to serve the app, and each has a free tier. Once clients are booking for real, the upgrade worth making is Supabase Pro, from $25/mo, less for the storage than for the pause, since a free project sleeps after a quiet week. Email works on Resend’s free tier for most small teams, and the Google calendar connection costs nothing. Nothing on the bill moves when a host joins the team.

Nothing here is proprietary. Your team, meeting types, hours and bookings sit in plain PostgreSQL tables that any Postgres host will accept from a standard dump, and your logo and cover are files you can copy like any others. That is worth more than it sounds in this category: the history of who met whom is the record of your client relationships, and it is exactly what makes a scheduling platform awkward to leave.

Yes, and it is worth doing before the link goes anywhere. Every host listed above attaches a domain in a few clicks with HTTPS included. Do it before the booking link goes into your email signature, your proposals and your website, because it also becomes the address in every confirmation email and the address your Google consent screen is verified against.

No, though you will type the occasional command: installing Claude Code, starting the app, applying a database change. The setup section above lists what you need, with a link for each, and once it’s on your machine Claude Code runs most of those commands for you.

Claude Code turns the real code into an app you can publish, with a database and user accounts. An Artifact is a one-file preview, good for a quick look but not for going live.

Claude Code’s plans reset on a rolling window rather than billing per token, so a heavy day of building can bump into a limit. You either wait for it to reset or move up a plan. Max gives more headroom for a long, from-scratch build. Nothing you’ve already built is lost either way, so the work only pauses.

References

Sources checked September 2026
  1. 01Breaking down the infinite workday, meetings across time zones (Microsoft WorkLab, June 2025). microsoft.com (published June 2025)
  2. 02The State of Meetings 2024, hours spent scheduling (Calendly, commissioned survey). calendly.com (survey fielded June to July 2024)
  3. 03Pricing (per-seat tiers, round robin on Teams), Calendly. calendly.com
  4. 04Pricing (Teams and Organizations per user, yearly), Cal.com. cal.com
  5. 05Pricing (Basic and Premium per user, both billing bases), SavvyCal. savvycal.com
  6. 06Pricing (annual plans, included seats), Chili Piper. chilipiper.com
  7. 07Pricing (Pro plan, free-tier limits, project pausing), Supabase. supabase.com
  8. 08Web developer hourly rates 2026 (freelance and agency benchmarks). developex.com
  9. 09Using OAuth 2.0 to access Google APIs (refresh token expiry in Testing), Google. developers.google.com
  10. 10Calendar API scopes and app verification, Google. developers.google.com
  11. 11Row Level Security, Supabase docs. supabase.com
  12. 12Vault (encrypted secrets in Postgres), Supabase docs. supabase.com
  13. 13Plans and pricing (Pro, Max), Claude. claude.com
  14. 14What is the Max plan?, Claude support. support.claude.com
  15. 15Set up Claude Code, Claude docs. code.claude.com
  16. 16Models overview, Claude docs. platform.claude.com

This guide is general information, not legal advice. What you may keep about a client, how long you may keep a record of who met whom, and what you must tell people before you write their details into somebody’s calendar vary by country and by state, so check your own rules before you collect anything. Third-party prices, plan terms, and market rates are quoted from the sources above and were last checked on the date shown. Vendors change them without notice, so confirm before you budget. Build hours and the cost estimates derived from them are our own estimates, not quotes. Claude, Claude Code, and the Anthropic API are products of Anthropic. Verify current capabilities and pricing before relying on them.