Build with AI

How to build an appointment booking system with Replit

Build and host your entire booking app inside one Replit workspace. Use simple prompts to set up service pricing, server-side slot availability, temporary holds, and database storage, then deploy to a live web address instantly.

August 2026 · 55 min read · Updated September 2026

Replit

$ Build an appointment booking system with a Postgres database in this workspace: services with prices and durations, availability worked out on the server from my opening hours and existing bookings, holds with an expiry, guest bookings behind a verified token, reviews, and an admin schedule.

  • Database provisioned in the workspace
  • Availability and holds built
  • Ready for you to publish
You describe it, Replit builds it
Start here

What an appointment booking system actually is

A calendar with a till attached. It has to know what you sell, how long each thing takes, when you are open, what is already taken, and what somebody is in the middle of taking, and be right about all five at the second a stranger presses the button.

Most small applications store what people type and hand it back later. This one is different in a way that shapes every decision below: the thing being sold is time, there is exactly one of each slot, and the answer to "can I have Tuesday at three" changes while people are looking at the page. That makes it a transactional application wearing the clothes of a calendar.

It is also why nearly every reader arrives at this page already renting one, and paying for it in one of two shapes. Either you are billed for each person or each calendar that can be booked, or you are billed for how many appointments you take in a month. Both meters are pointed at growth: the first at hiring, the second at being busy.

What makes it genuinely hard to build is not the grid of times. It is that the grid is a conclusion, drawn from your opening hours minus the length of the service minus everything already booked minus everything currently held, and that the conclusion has to survive two people acting on it at once. Get that wrong and you have not shipped a bug, you have double-booked a customer who took an afternoon off work.

The calendar is the easy half

Drawing a month of dates is a component you will finish in an afternoon. Deciding whether the 3pm inside it may be offered is a question about opening hours, service duration, existing bookings, and unfinished ones, and it belongs on the server where all four of those live. Build the answer first and the calendar becomes a way of displaying it.

Two people, one slot, the same second

This is the failure that defines the category. The fix is two-part and neither half is optional: hold the slot while somebody fills in their details, so it stops being offered, and check again at the moment the booking is written rather than trusting what the browser was shown thirty seconds ago.

The appointment you took is not the appointment that happens

Between the booking and the day, people forget, reschedule, and quietly do not turn up. Which of those you plan for (a hold that expires, a reschedule that moves rather than deletes, a policy about cancelling late) is a business decision you make in words before any of it is code.

What happens to appointments once they exist

20.8%

of appointments were no-shows at the primary care network measured in a study published in January 2025 (a network handling over 140,000 visits a month), falling to 10.25% after the changes the paper tracked. That figure is from healthcare, and your own trade may run kinder or harsher, but the shape of it travels: the appointment on your calendar is a promise, not an attendance.

JMIR Formative Research, published January 2025 (read on PubMed Central) · checked study published January 2025

What a booking system needs

The parts every booking system is built from

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

01

An answer to “is this slot free”, computed rather than assumed

Take the day’s opening hours for that service, cut them into slots the length of the service, remove everything already booked, remove everything somebody is currently holding, remove anything in the past, and what remains is what you may offer. Every one of those five inputs lives on the server, so the answer does too, and the browser gets told, never asked. This is also the piece worth over-building, because it is the only part of the application whose failure is visible to two customers at once.

02

A service is a duration and a price, not a name

The length of the thing you sell is what decides how the day divides up, so it belongs on the service rather than in a global setting. Once one service runs 30 minutes and another runs 90, the same Tuesday produces two different grids, and a service that is only offered on certain days needs its own opening hours, sitting over your general ones.

03

The hold, and the customer who wanders off

Somebody picks 3pm and starts typing their phone number. For the next few minutes that slot has to stop being offered to anybody else, which means a hold with a clock on it rather than a booking. Then the harder half: most of those people finish, and some close the tab in a car park. Something has to notice a hold that expired and hand the time back, or your calendar slowly fills with appointments nobody made.

04

A booking has a life, not a status

Requested, confirmed, moved to next week, finished, called off the night before. Model that as a lifecycle and the awkward questions have answers: whether a customer may cancel two hours ahead, whether a reschedule keeps its history, what a completed appointment unlocks. Model it as a text field and you will be reading your own database to work out what happened.

05

The customer who will not make an account

A first-time customer with a phone in one hand does not want a password. Taking the booking with an email address is easy. The interesting part is how they come back to it, because a link that works must not be a link that works for everybody. That means a long unguessable token with an expiry, checked together with the email address, rather than a booking number in a URL.

06

A rating only a real customer can leave

Reviews are worth having precisely because they are hard to fake, so the rule that a review requires a finished appointment of your own is the feature rather than a validation detail. Put that condition in the database and it holds no matter which screen is asking. Leave it in the form and your service pages become a place strangers post.

Build vs buy

Build it once or pay per booking

Vendor pricing scales with your team size ($10-$61/mo per seat) or booking volume (free tiers cap at 50-200). Calculate both before choosing.

Build your own

An app you own has neither meter on it. Nobody counts your staff and nobody counts your appointments, and with an AI coding tool writing the availability function, the holds, and the access rules, that build is weeks rather than quarters.

  • The fifth person taking bookings costs nothing, so putting somebody else on the rota is not also a software decision
  • The four-hundredth appointment in a month costs exactly what the fourth one did
  • Your services are pages on your own domain rather than a widget pointed at a vendor’s subdomain
  • Every booking, customer, and review sits in your own database, queryable without an export request
  • How long a slot is held, how late somebody may cancel, and what counts as available are your rules to write
  • Taking a booking from somebody who refuses to make an account is a decision rather than a plan feature

Rent the scheduler

Calendly · Acuity · SimplyBook.me · Setmore

What renting buys is a decade of scheduling machinery, and some of it is genuinely tedious to reproduce. Reminders that leave the building, sync with the calendar your staff already keep, the arithmetic of time zones and the weekend the clocks change, taking a deposit at the moment of booking, and intake forms you would otherwise scope one at a time.

  • Working on the day you sign up, with the calendar, the reminders, and the clock arithmetic already correct
  • Reminders that actually reach the customer, by email and often by text (this template notifies inside the app and sends nothing out of it)
  • Money at booking time, a deposit or a card kept on file, which this template has no version of at all
  • Sync with the calendar your staff already live in, so a dentist appointment in a personal diary blocks a work slot
  • Somebody else’s problem the weekend the clocks change, and every time a customer books from another country
  • Every one of the four bills for growth: two per person or calendar, two by how many appointments you take
CalendlyStandard $10 and Teams $16 per seat/month billed yearly, with Enterprise from $15k/yr

The default answer when somebody says “send me a booking link”, and the one whose free tier is ruled out by shape rather than by volume: Free gives you “1 event type” and “Connect 1 calendar”, so a catalog of six services does not fit inside it however quiet you are. The page quotes both paid tiers as billed yearly and advertises the annual saving at 16% and 20%, so month-to-month runs higher than either figure. It published no monthly number to our reader, so none is quoted here. Worth knowing what it is built for: meetings between people, rather than a shop window listing what you sell with a price and a length against each item.

calendly.com · checked August 2026

Acuity Scheduling$20 (Starter), $34 (Standard), and $61 (Premium) per month, or $16, $27, and $49 billed annually - for 1, up to 6, and up to 36 calendars

The closest of the four to what this template does, and the one that prices the thing this template gives away: a calendar is a staff member or a room, and you buy them in blocks of 1, 6, and 36. No free tier exists, only a “7-day trial, no credit card needed”. Its features page is also the honest list of what you are choosing not to have: “automated email confirmations, updates, and reminders (*SMS reminders available on Standard plan+)”, “Sync personal and business calendars to avoid double-booking”, and “Collect prepayment, partial deposit, or securely store credit card details at booking”. The first and third of those are additions on a build you own.

acuityscheduling.com · checked August 2026

SimplyBook.meFree (50 bookings/month), then €11.9 (Basic, 100), €24.9 (Standard, 500), and €49.9 (Premium, 2,000) per month billed annually - €13.9, €29.9, and €59.9 billed monthly

Included because it states the per-appointment model more plainly than anybody: the plan ladder is a monthly booking cap, so the bill is a function of how busy you were. Do that multiplication before comparing seat prices: 500 appointments a month is a small salon, and it is the middle rung. The second meter is the one people meet later: “custom features” are capped too, at 1, 3, 8, and unlimited, and features here means things like an intake form or a cancellation policy. Prices are quoted in euros because that is the currency its page served us. The page shows annual billing saving up to 17%.

simplybook.me · checked August 2026

SetmoreFree for up to 4 users and 200 appointments a month, then Pro from $5 per user/month billed annually

The most generous free tier in the set, and the clearest illustration of the argument: it stops at “200 appointments” a month, which is about seven a day. That is the point at which a service business is working rather than starting, so the free plan ends exactly when the thing you built it for begins. Free covers up to four users with email confirmations and reminders and a branded booking page. Pro lifts the caps and adds text reminders and two-way calendar sync. The page’s annual figure is $5 per user a month and its month-to-month figure is higher, without stating the basis plainly enough to quote.

setmore.com · checked August 2026

Rule of thumb: if several people work a rota, money changes hands at booking time, and you would rather never think about a reminder or a time zone again, rent. Those are real products and none of them is a weekend of describing. If the shape of your problem is that your own site should show what you offer, at your prices, with your rules about cancelling, and you would like the bill to stop growing every time you get busier, that is the half worth owning. Two findings worth weighing whichever way you go. In an MGMA poll of 622 medical groups published in January 2025, 42% charged a no-show fee, and those that did reported more improvement in their no-show rates over the year than those that did not, 25% against 16%. And in a second MGMA poll, published in July 2025 with 244 responses, 71% of practices had fewer than a quarter of their patients self-scheduling at all. Offering online booking and having it used are two different projects, and the second one is mostly about telling people it exists.

No dev needed

Why build with Replit

A real app needs somewhere durable to keep what people enter, rules about who’s allowed to see it, and a place to actually run once it’s built. Those are three separate problems, and most solo builds solve them badly, or not at all.

Replit’s Agent handles all three from one chat, in the same workspace the app ends up living in:

The build loop
1

Describe

Tell the Agent what to build, in plain language.

2

Watch

It writes the code, sets up the database, and shows the app running live.

3

Try it

Use the real app in the preview rather than a mockup.

Publish

Take it live on Replit’s own hosting, or ask for the next change.

Loop back to Describe

The build and the place it ends up running are the same workspace throughout, so there’s no separate hosting account to set up later.

One workspacebuilds, runs, and hosts it

Replit is the one tool here that also deploys what it builds. Publishing takes the same project live on Replit’s own infrastructure, with a working domain, uptime monitoring, and security scanning included.

Managed Postgres with 20GB included free

Ask the Agent to add a database and it creates the schema and wires your app to it. What you get is a real, fully-managed SQL database rather than a mocked one.

Up to 10 Agent sessions in parallel (Pro)

Core allows up to 2 parallel Agent sessions and Pro allows up to 10, so more than one part of the app can be worked on at the same time.

What it costs

Pay a developer, or do it with AI

Commercial booking tools bill for either the people on your schedule or the bookings they take. Calculate your team size and expected volume, because those are the two lines that drive your bill in year three.

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 rather than a wide guess. The part worth reading twice is where those hours sit: availability, the holds that keep a slot from being sold twice, and the safe way a guest returns to their own booking account for roughly a third of them, and not one of the three shows up in a screenshot. That is the usual reason a quote for “a booking page” comes back at several times what the mockups suggest.

Build it with Replit

From scratch, with Replit
Replit
Free (daily credits) to $25/month (Core) or $100/month (Pro)
Database (built-in Postgres)
Free to start · 20GB included
Hosting (Replit Deployments)
Billed separately, on top of the plan
Your time
~110 hrs

Free to try the idea, ~$25-$100/month on Core or Pro while you build a real one, then whichever plan (plus any deployment cost) you keep using

Replit’s plan price and its credit grant are the same number, not a subscription plus a separate credit purchase: Core is $25/month for $25 of monthly credits (or $20/month billed annually), Pro is $100/month for $100 of monthly credits (or $95/month annually). Once you publish, Replit bills hosting through its own Deployments separately, on top of whichever plan you’re on. Budget for it as a second line, not folded into the $25 or $100.

* 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 and services are small enough that only the photographs of what you offer will ever push at those. 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 business that looks closed, which lands squarely in the week after launch, before anybody has found you. 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.

The two meters a rented scheduler runs are the ones missing from this table. One charges for every person whose diary can be booked, the other for every appointment that gets taken, and both grow as the business does. Neither column above has either, so your busiest month costs exactly what your quietest one does, and the only line that moves is whichever AI model you decide to call. That shape suits a business whose bookings are going up, which is the only kind of business anybody is trying to build.

Prices and rates from supabase.com, developex.com and replit.com, checked August 2026.

Plan first

Decide before you build

Six things to settle in writing first. Every one of them is a promise to somebody who is about to arrange their day around you, and each costs far less to decide now than to unpick once real appointments are in the calendar.

01

Whether somebody can book without an account

Settle this before the schema, because it reaches into every table. An account gives a customer their own history, where most follow-up questions answer themselves, but demanding one from a first-timer holding a phone loses the booking outright. The middle path: take the appointment from any email address, then let them claim it later.

02

What available actually means in your business

One diary, or one per person? A room that hosts one thing at a time, or a class with twelve places? This shapes the availability function, and honesty beats ambition here: a single shared calendar with your real opening hours is a working product, while a half-built per-staff model produces double bookings.

03

How long you hold a slot, and what happens when it expires

Too short and you lose bookings from people who type slowly. Too long and your quietest-looking Tuesday is full of ghosts. Fifteen minutes is a reasonable start. The half people forget is the expiry: something has to sweep up abandoned holds, and a customer coming back to a lapsed one thinks they have an appointment.

04

Your cancellation and no-show policy, in words first

How late may somebody cancel and still be fine? What happens if they simply do not arrive? Write the sentences in the language you would use to a regular customer, and the software becomes a question of where to show them. One caution: a policy that mentions a fee needs a way to charge it (see 06).

05

Whose clock the appointment is in

Almost every booking bug that survives to production is a time-zone bug. Store the moment in one absolute form on the server, decide which zone your business runs in, and show it in the customer’s own. Then test the awkward cases on purpose: a customer two zones away, and the weekend the clocks change.

06

Whether money changes hands at the booking

Recording an appointment and charging for it are separate projects, and shipping the first without the second is fine. Most small businesses take payment on the day. Decide deliberately, though: a deposit changes what a cancellation means, needs a refund path, and brings a payment provider into the security decisions below.

Approaches

Comparing your build options

Connecting separate databases, backend servers, and hosting eats up most development time. Compare three ways to launch: writing code from scratch, using a basic UI kit, or building inside Replit, where your database, server logic, and live site live in a single workspace.

~230 hrsBuilding by hand

The screens are not what takes the time. Working out whether a slot is free means reading your opening hours, the length of the service, everything already booked, and everything somebody is halfway through booking, and then being right about it while two strangers press the same button. That part is a day of thinking and a week of edge cases.

~170 hrsGeneric UI starter kit

A starter kit hands you a calendar, a form, and a dashboard shell, which feels like most of the job and is the part you would have finished anyway. Nothing in it knows what you sell, how long it takes, when you are open, or that the 3pm on screen was taken ninety seconds ago. All of that is still yours to write.

~110 hrsBuilt with Replit

One request at a time to the Agent, with the database, the server, and every screen written inside the workspace that ends up hosting them. Sign-in belongs to you here as well, since on this tool the only thing able to tell the database who is asking is your own server.

Interactive calculator

Estimate your exact build timeframe

Not every project needs all six features. Uncheck the options your business doesn’t require, like guest checkout or online payments, to calculate your real build time.

What your booking system needs

Your estimate

110 hrs

start to finish

Based on the 6 of 6 features you’ve selected, plus ~26h 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

Replit runs entirely in the browser, and it’s the one tool here that also hosts what you build, so no GitHub account is required first. Before step 01: an account and a plan. A database comes later, the moment your app actually needs one, and GitHub whenever you want a copy of the code outside Replit.

1

Replit account

Cost: Free

Sign up and you land in a workspace with an Agent chat, the code, and a live preview side by side, with nothing to install.

Sign up for Replit
2

Replit subscription

Cost: Free (daily credits), then $25/month (Core) or $100/month (Pro)

Starter’s free daily credits are enough to try an idea, not to finish one. Core is $25/month billed monthly, or $20/month billed annually, for $25 of monthly credits and up to 2 parallel Agent sessions. Pro is $100/month monthly, or $95/month annually, for $100 of monthly credits, more collaborators, and access to the strongest available models. The price you pay and the credits you get are the same number on both plans, so you have no separate subscription-plus-credits split to work out.

Compare Replit plans
3

Replit database (Postgres)

Cost: Free to start · 20GB included

Every Replit app includes its own managed Postgres database with 20GB of free storage. Ask the Agent to add one and it creates the schema and connects your app to it, with no separate account to create anywhere else.

Replit’s built-in database, Replit docs
Optional
4

GitHub connection

Cost: Free

Not needed to start, and not needed as an undo either, because Replit checkpoints the whole workspace as the Agent works. Connect a repository from the Git pane, free on every plan, and a copy of the real code lives outside Replit under your own account. Worth doing once the project is one you would hate to lose.

Using the Git pane, Replit docs

The first two are all you need to start. Everything here stays inside the one browser tab, the app included once you publish it, and the GitHub copy is the one deliberate exception.

Step by step

Build your booking system, one Agent message at a time

Zero complex setup required. The Replit Agent automatically creates your code, provisions a built-in database, and configures user security, all through simple chat instructions.

  1. 01

    One message for the app, the database, and the ground rules

    Postgres is part of this workspace rather than an account you go and open, so it belongs in the opening request, together with the two constraints the rest of the build stands on.

    PromptSet up the project and the database
    Set up a React 18 + Vite + TypeScript app with Tailwind and a server, and add a Postgres database to this Repl, the one Replit provisions, not anything outside. Write a short notes file at the project root recording three things. This is an appointment booking system. The words throughout are service, duration, opening hours, slot, availability, booking, hold, guest, and review. And two standing rules: whether a slot is free is worked out on the server from my opening hours and existing bookings and worked out again inside the write that creates a booking, never taken from the client, and every list of another person’s appointments is narrowed in the database rather than on a page, with a guest reaching their own booking going through a server-side token check rather than a rule that opens the table. Keep the database connection details in Replit’s Secrets rather than in the code.

    Both rules go in the file, not only in this request. Trusting a slot the page already knows about is what any assistant reaches for once the booking form obviously has the answer in hand, and on this app that particular shortcut is how two customers turn up for the same appointment.

  2. 02

    The catalog and the shop window, checked at a checkpoint

    Schema and public pages in one go. Nothing writes anything yet, which makes this the inexpensive moment to discover your service list is organised the wrong way round.

    PromptModel the catalog and build the public pages
    Design the schema and the server routes over it. Services with a title, description, category, price, one or more durations in minutes, an image, and optional opening hours of their own. A settings table holding my default weekly opening hours, the slot length, how many minutes a slot is held, my currency, and my cancellation policy as text. Seed eight services across three categories with deliberately mixed lengths (a 30-minute one, a 90-minute one, and one offered on two days a week only) plus opening hours with one day closed. Then the public side over it: a landing page, a catalog with category filters showing each price and length, and a service page with photos and a place for reviews. No accounts and no bookings in this message.

    Open your own catalog in the preview before going any further, and take the checkpoint while you are there. How you group services is the one structural choice customers navigate with their thumbs, and a grouping that read beautifully as a list of words rarely survives becoming a menu.

  3. 03

    Availability in Postgres, written by the Agent

    The step that decides whether the times on screen mean anything. Ask for it in the database explicitly, and judge it on the slots it takes away rather than the ones it offers.

    PromptWork out availability properly
    Build availability in Postgres rather than in the application. Given service ids, a date range, and the duration the customer picked, return only genuinely free slots: for each day take that service’s own opening hours where present and my defaults otherwise, cut the day into slots of the requested duration, then remove anything in the past, anything overlapping a booking with status confirmed or pending, and anything overlapping a hold that has not expired. Store appointments as absolute moments. Expose it through one server route the picker calls, and do not fetch bookings and filter them in the route. Build the picker over it with a clear empty state for a closed day. Then, in the preview, print the working for one specific Tuesday (which slots each rule removed and why) and show me what the picker offers for a day I have deliberately booked solid.

    This is the step where checkpoints earn their keep. Availability reaches into the schema, and a rollback here offers to take the database along with the code, a gift while every row is seed data you made up, and a decision worth pausing over the moment real appointments are in there.

  4. 04

    The hold, the guest token, and photos your server hands out

    Bookings that leave a slot out of circulation while somebody types, a guest who has no account, and one decision about files that does not come up on the other tools.

    PromptTake the booking, with a hold behind it
    Build the booking side. A booking records the services and durations chosen, its absolute start, a status of pending, confirmed, completed, or cancelled, its customer or a guest name and email, notes, and a hold expiry. Picking a slot writes a pending booking held for the minutes in my settings, removing it from availability at once. Confirming makes it confirmed and clears the hold. Inside that write, work availability out again and refuse the booking if the slot has gone, with a message rather than an error. Add a cart so several services become one appointment long enough for the total. For guests: a name and an email, a long random token with an expiry generated on the server, and a lookup requiring the token, the email, and the booking id together. Then the service photographs: uploaded through my own server into object storage, with the catalog images served publicly but the upload route open only to me later, once roles exist. Finally, show me two requests confirming the same slot at the same moment, and one of them refused.

    Insist on that last demonstration as running code. On a tool where the preview, the database, and the eventual host are all the same workspace it is tempting to trust what you can see working, and a booking form used by one person at a time is the one thing this bug cannot be caught by.

  5. 05

    Sign-in your server owns, then rules that read what it says

    Nothing hands this database an account id by itself, so the Agent builds both ends of the chain: the sessions your own server issues, and the policies that go looking for whichever identity it has just announced.

    PromptAdd sign-in, roles, and access rules
    Build sign-up, login, logout, and a server-side session on email and password, with one profile row per account. Add a roles table giving each account customer or admin, in its own table, never on the account record, since anything there is editable by that user. Then turn on row-level security across every table: have the server declare the current account and its role as session-local settings at the start of every request, and write the policies to read them. A request with no account declared may read services, the settings the page needs, and approved reviews, and nothing else. A customer reads and cancels only their own bookings. An admin reaches everything. A guest reaches their own booking only through the server-side token lookup, so no policy opens the bookings table to an undeclared request. Explicit with-check clauses on inserts and updates, and a review allowed only where a completed booking for that service belongs to that customer. Then show me how to prove, as a signed-in customer, that another customer’s booking comes back empty, that an undeclared request cannot list bookings, that a guest lookup with the wrong token returns nothing, and that a review without a finished appointment is refused.

    Nothing hosted is handing Postgres an account id here, which leaves your own server as the only part of the system that knows who is asking. Prove the announcement works before writing a policy that depends on it: a policy with nothing to read does not complain, it simply lets everybody through, and what it would be letting them through to is the name, number, and Thursday afternoon of every customer you have.

  6. 06
    Destination

    The back office, a Scheduled sweep, and publishing

    The admin screens, then the one piece of this build that is not a request from a browser at all, and on this tool it is a deployment of its own rather than a database feature.

    PromptAdd the back office, the sweep, and publish
    Three things left. First, the back office: a schedule by day and week, bookings I can add and cancel from it myself, a bookings manager filtered by status and service, a reschedule that moves an appointment and keeps its history, a cancellation window read from my settings, a service editor with photo upload and per-service opening hours, a settings screen, review moderation, in-app notifications on a new or moved booking, and a dashboard charting bookings and the value booked by service. Second, the sweep that cancels pending bookings whose hold has expired: authenticate it with a secret from Replit’s Secrets rather than a session, make it safe to run twice, and set it up as its own Scheduled deployment rather than something the app does when somebody happens to visit. Third, help me work a whole day: book as a stranger, abandon a booking and watch the slot come back once the sweep has run, follow a guest link, reschedule as a customer, try to cancel too late, add a walk-in from the schedule, moderate a review, check the dashboard, and when that holds, take me through Publishing: which deployment type suits the app, why the sweep is a second one, and who the app ought to be visible to on day one.

    Publish the sweep separately and then actually wait for it once. A scheduled job that was never triggered looks identical to one that works, and the first evidence you get either way is a calendar that either frees itself up overnight or quietly fills with appointments nobody made.

Authentication & security

Protect the calendar and your customers

A booking entry holds more than a name: it reveals where a customer will physically be at a specific hour. What follows are the database-level rules and server-side policies that keep every record strictly isolated and protected.

Standard Password Protection

Sign-in is built into the app rather than delegated to a hosted identity service, so sessions live on your own server, which is also the only thing able to tell the database whether the account asking for a booking is the customer it belongs to.

Separate Admin and Customer Access

Customer and admin, which is genuinely all a single-location business needs. What makes the rules interesting here is the other two cases: an unauthenticated visitor who may read your catalog and nothing else, and a guest with no account who must reach exactly one booking: their own. Most access-rule mistakes in this application happen in that second case rather than between the two signed-in roles.

Automatic Double-Booking Protection

If the page posts “this slot is free” along with the booking, then the way to book a slot that is not free is to change what the page posts. Your server has to re-derive availability from the opening hours and the existing bookings at the moment it writes the row, and refuse the write when the answer has changed since the customer was shown it.

Data Rules Protected from Tampering

What Replit provisions is ordinary Postgres, so its policies behave the way Postgres policies always behave. What differs is the source of identity. Nothing hosted is handing the database an account id here, so the Agent has your own server announce who is asking and in which role before each request touches a table, then writes every policy to read that announcement. Miss it and the policies do not complain. They simply admit everybody, and on this app what they admit everybody to is your entire diary.

Strict Privacy for Customer Profiles

The template’s migrations declare 68 row-level security policies, a good number of them later revisions of earlier ones, which is what tightening a rule looks like in a migration history. The count is structural rather than anxious. Take the bookings table: the customer it belongs to may read and cancel it, a guest may reach it with a token, an admin may see every one, and an undeclared request may see none. Four rules on one table, before you reach the other eight.

Private & Secure Booking Links

Letting somebody find their booking without an account means something in that flow stands in for a password. A booking number does not: they are short, they look sequential, and people forward them. Generate a long random token, give it an expiry, and check it together with the email address and the booking it belongs to, so holding any one of the three is not enough.

Bot & Brute-Force Protection

A public route that answers questions about bookings is worth somebody’s time to guess at, so write every attempt (successful or not, with the address it came from) to an audit table, and rate-limit by address. Worth knowing where the rough edge is on any deployment that can run more than one instance: a rate limit kept in one process’s memory resets whenever a new instance starts, so keep the audit table either way and move the counter somewhere shared if your page gets real attention.

Prevent Unauthorized Admin Escalation

Roles want a table of their own for one narrow reason: a customer can edit their own account record. Store the role there and promoting yourself to admin is a profile update, and an admin in this application reads every customer’s name, number, and where they are due to be on Thursday.

Privileged Actions Run Server-Side

Working out availability, holding a slot, confirming a guest’s booking, and sweeping up abandoned holds are each several operations at once, and each has to be permitted more than the person who triggered it. That is server-side work carrying the rule in its own code, above the access rules, and the database connection it runs with belongs in Replit’s Secrets, never in anything the browser downloads.

Protected Scheduled Jobs

The sweep that releases expired holds is not called by a person, so a sign-in cannot protect it. It gets a shared secret instead, checked on every call and kept in Replit’s Secrets rather than in the code. A scheduled endpoint with no check on it is a public endpoint that cancels bookings, and it will be found.

Location Data Treated as Personal Data

Most records in most applications are dull. “This person will be at this address at this time” is not, particularly for a clinic or anywhere visited alone. Decide who on your team may read the diary, how long you keep past appointments, and what a customer gets if they ask you to delete theirs, and remember reviews and no-show history are attached to a name too.

Automatic Workspace Backups

The Agent checkpoints as it works (files, configuration, and optionally the database) so a bad change is a click back rather than an afternoon. Pro adds a 28-day database rollback on top. Worth having in place before the diary is the only record of next month, because unlike most data in a small business, a calendar cannot be reconstructed from anywhere else: the people in it are assuming you know when they are coming.

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.

Paste this into the chat before launch so the Agent checks nobody can see data they shouldn’t.

One rule outranks the rest here: the database connection, any AI provider key, and the secret guarding your scheduled sweep belong in Replit’s Secrets and nowhere else: not in the app, and not in a repository you push. Treat any of the three that escapes as burned, and replace it the same day.

Workflow rules

What speeds the build, and what slows it

Speeds the build

  • One small, specific request per message, checked in the live preview before the next one
  • Letting the Agent provision the database from the chat instead of wiring one up by hand
  • Running two Agent sessions in parallel on unrelated parts of the app, once your plan allows it
  • Rolling back to a checkpoint the moment a change goes wrong, instead of unpicking it by hand
  • Reviewing what Publishing changed, meaning the domain, who can reach the app, and the machine it runs on, before the first release

Slows the build

  • Asking for the whole app in one message instead of one piece at a time
  • Building screens for data that isn’t in the database yet
  • Running unrelated Agent sessions against the same files at the same time
  • Letting several risky changes stack up before checking whether any of them actually broke something
  • Publishing without checking who the app is visible to first
Keeping a safe copy

Connecting GitHub (Optional)

Every change in Replit is saved automatically without any technical setup. Checkpoints are the day-to-day undo. You only need to link GitHub if you want a private copy under your own control or plan to hand the codebase over to external developers.

Every milestone is already saved

Replit’s Agent creates a checkpoint automatically at key points as it works: a full snapshot of the files, the configuration, and even the AI conversation itself, not just the code.

Checkpoints and rollbacks, Replit docs

Rolling back restores the whole workspace

One click returns your project to an earlier checkpoint (files and configuration together, and optionally the database), which is broader than a typical code-only undo, so a rollback after real data has changed is worth a second look before you confirm it.

GitHub keeps a copy outside Replit

Connect a repository from the Git pane, free on every plan, and stage, commit, and push changes back to GitHub with a click, or pull in anything changed outside Replit.

Using the Git pane, Replit docs

It’s also how an existing project gets in

Point Replit at a public repository’s URL for a fast import, or use the guided import for a private one. Either way, Replit detects the stack and installs everything on its own.

Import from a provider, Replit docs

You rarely type git commands

The Git pane’s buttons cover staging, committing, and pushing. If you’d rather type them yourself, the workspace Shell stays in sync with whatever the pane just did.

Going live

Going live without external hosting

Skip third-party hosting and external database setup. Your database, backend, and domain live in the same Replit workspace. Just click Publish to go live.

HostBest forNotesFree tier
AutoscaleThe booking page and the back officeGrows with traffic and shrinks back when nobody is booking, which suits this app well: bookings arrive in bursts around the times you advertise and almost nothing happens overnight. It is the default choice for the app itself, and it is enough for everything a customer or you actually click.Metered - billed with your plan
ScheduledReleasing abandoned holdsRuns on a timer instead of answering requests, which is exactly the shape of the sweep that finds pending bookings whose hold has expired and cancels them. Publish it separately from the app, keep it safe to run twice, and give it a secret from Replit’s Secrets rather than a session. Without this one, your calendar slowly fills with appointments nobody made.Metered - billed with your plan
Reserved VMSteady traffic all dayDedicated compute that never sleeps. Worth comparing against Autoscale if your booking page is busy through the whole working day rather than in bursts, or if you later add something that needs to hold a connection open. For most single-location businesses it is more than the app needs.By machine size - billed with your plan
StaticNot this appFiles only, with no server behind them. Listed to rule out: availability is computed in the database, the access rules need your server to declare who is asking, and the guest lookup is a server route checking a token, so nothing in this build fits here.Metered - billed with your plan

All of these are Replit rather than a third party, so the choice is shape rather than vendor, and this build wants two of them: one to serve the app, and Scheduled for the sweep. Review who the app is visible to before the first release, since Publishing is what sets it.

Two things to check on the day you publish, and neither is the hosting. The first is the clock: the server stores a moment and the browser draws it in local time, so open your published booking page with your machine set to another time zone and confirm the slot you booked is the slot that appears, then do it again around a daylight-saving change if you work early or late. The second is that the sweep only exists if you published it: a Scheduled deployment is a separate release from the app, and an app published without one looks completely healthy while its calendar quietly fills with holds nobody came back for.

Database & backend

Your database is already part of the workspace

Nothing to connect. Services, bookings, and customers are small and will not trouble the included allowance for years. The photographs of what you offer are the part that grows, and they belong in object storage rather than in a table.

ServiceBest forNotesFree tier
Replit PostgresData, built inManaged Postgres with 20GB included free, provisioned from the same chat that builds the app, and since it is ordinary Postgres, the availability function from step 03 and the access policies from step 05 both work exactly as they would anywhere else. What it does not include is a hosted identity service, which is why your own server is what declares who is asking before any policy can act on it.Free to start · 20GB included
AI workflows

Where AI genuinely helps a booking business

Each of these is one more prompt once your booking system is running, so copy any of them in as they stand. Every feature reaches the model through a single server-side function, which is the only place your API key ever sits.

Turn “any chance of Tuesday afternoon?” into a bookable slot

The message arriving by text, email, or Instagram is how a lot of appointments still start, and retyping them into your own system is the daily tax. This is the right first feature because it is contained, it saves time immediately, and it never touches the diary without you.

PromptTurn “any chance of Tuesday afternoon?” into a bookable slot
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 customer. Send the message to that function and get back a structured guess: which of my services they seem to want, roughly when they are asking for, and the name and contact detail if the message contains one. Then match that guess against real availability and show me the three closest free slots as a draft booking I confirm or discard. Never write a booking directly from the model’s output, and where the message is ambiguous say so rather than choosing for me. If it says “sometime next week” I want to see that, not a Tuesday you picked.

Offer a cancelled slot to whoever actually wants it

A cancellation at 9am for a 2pm appointment is money you can still recover, and the work of recovering it is going through your own list deciding who to ask. That is exactly the sort of judgement a model can draft and you can approve.

PromptOffer a cancelled slot to whoever actually wants it
When a booking is cancelled, build me a shortlist for the freed slot: customers who asked for that service, whose earlier bookings suggest they are around at that time of day, who have not already got an appointment that week, and who have not asked me to stop contacting them. Send only what my ai function needs to rank them and nothing else: no contact details in the prompt. Show me the list with a one-line reason each, and let me pick who gets the message. Nothing goes out automatically, and anybody who has opted out is filtered before the model sees them.

Draft the awkward reply, with your own policy in front of it

A late cancellation, a reschedule for the third time, a customer asking to be squeezed in on a closed day. The words are the work here, and getting them consistent is worth more than getting them fast.

PromptDraft the awkward reply, with your own policy in front of it
Add a “draft a reply” action on a booking that sends the booking, its history, and my cancellation policy text to my ai function and returns a short, warm reply I can edit before it goes anywhere. Rules: it may only state what my policy actually says (if the policy is silent on something, the draft says it will check rather than inventing a rule), it never offers a slot without checking availability first, and it never promises a refund or a waived fee, because this application does not take payment and I am the one who decides that.

Turn a month of reviews into a list of things to fix

Ratings tell you the temperature. What you want is the pattern: the same complaint three times, always for the same service, always on the same day of the week.

PromptTurn a month of reviews into a list of things to fix
Add a panel on the admin dashboard that groups the last period’s reviews by what they are actually about, using my ai function, and returns each theme with a count, one representative quote, and which service and which day of the week it concentrates on. Send the review text with customer names removed. State counts as figures rather than describing them vaguely, print the period it covered beside the result, and where a theme rests on one or two reviews say so instead of presenting it as a trend.

Ask your own calendar what went wrong last month

Your dashboard answers the questions you had when you built it. What turns up later is which slots get abandoned mid-booking, which service attracts the no-shows, and whether the people who booked three weeks ahead were the ones who did not arrive.

PromptAsk your own calendar what went wrong last month
Add a panel that answers questions about my own booking history through my ai function: no-show and cancellation rates by service, by day of the week, by time of day, and by how far ahead the booking was made, plus how many holds expired without becoming bookings. Have it compute the figures 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 customer names or contact details at all.

A cheap model is plenty for most of the prompts above. Save Pro’s stronger models for the one or two spots where the extra reasoning actually pays for itself. Add any provider key through Replit’s own Secrets tool rather than hard-coding it, and keep every AI feature behind one server-side function so a single key covers the whole app.

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 booking page can begin. This one exists, runs, and takes bookings, so the weeks that availability, the holds, and a safe guest path would have cost turn into an afternoon of typing in your own services and your real opening hours.

Appointment Booking System

The exact booking system this guide builds, packaged so you can open it, point it at your own backend, and make it yours from there. A booking platform for service businesses that runs both sides of every appointment. Customers browse your services, see live availability, book their own slot, and leave a review afterward - while you handle the schedule and everything around it from one admin panel.

React 18ViteTypeScriptTailwind CSSSupabase
Out of the box

The key benefits of starting with a template

The availability already comes from your opening hours, and the slot already stops being offered while somebody is finishing. That is most of what this saves you. Behind it, the guest path, the cart, the reviews, the notifications, and the admin schedule 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. The ~1 hr is what adopting the built one costs: connect a database of your own, then put in a first handful of services and your real opening hours. Settling your prices, your durations, and your cancellation policy is work whichever path you take, so it sits outside both figures.

Availability that already refuses to double-book

A server-side function works out free slots from each service’s own opening hours merged over your defaults, the slot length you set, the duration the customer picked, and every booking already confirmed or pending, holds included. The browser is told what is free and never asked. Slots are held for the number of minutes you choose, fifteen by default, and a scheduled sweep gated behind its own secret cancels the ones nobody finished.

Guest bookings, done the careful way

A customer books with a name and an email address and no password. Coming back to that booking goes through a long random token with an expiry, generated by a database trigger and checked together with the email address and the booking it belongs to, with every attempt, successful or not, written to an audit table and rate-limited by address. That is the part most builds get wrong on the first pass.

Two roles across 68 declared policies

Customer and admin accounts, with roles kept in their own table behind a security-definer check so nobody can promote themselves, and 68 row-level security policies declared across the migrations as those rules were written and tightened. Around them, 34 server-side functions for the work that has to outrank the person asking: availability, holds, confirmations, the guest lookup, and the sweep.

A back office that runs the day

A schedule you can work from behind the desk, with bookings you add and cancel yourself, plus a service editor with photo uploads, per-service opening hours over your business defaults, a bookings manager, review moderation, in-app notifications when something arrives or moves, and a dashboard with charts over what actually sells.

A codebase your AI tool can keep extending

Types on everything, folders that follow the features rather than the file extensions, and a comment wherever the reasoning would not be obvious to somebody reading it cold. Availability is where that pays off, because it is the part you are most likely to want changed (a diary per staff member, a class with twelve places), and the version in front of you states plainly which inputs each answer was drawn from.

Customer story

From founders who build on our templates

Rather than starting from scratch, we built on this foundation using our AI workflow. It allowed us to launch a complete, reliable product for our users with minimal friction.
Jeevan ThomasJeevan ThomasFounder & CEO, Hado.ai
Got questions?

Common questions

No, and this is the first thing to know before you compare it with anything. The template notifies inside the app (a booking arrives, a booking moves, a review lands) and carries no mail or text provider anywhere in it, so nothing reaches a customer’s inbox or phone. Connecting an email service is a small, well-defined addition, and it is the one to make first: a reminder the day before is the cheapest thing in this whole category, and a confirmation somebody can find in their inbox saves you half your messages.

Not as it stands. There is a cart and a guest checkout form, but no payment provider is wired in. A booking is recorded, not charged. Plenty of service businesses run exactly that way and take payment on the day. If you want a deposit, it is a real addition rather than a switch: a provider, a refund path, and a decision about what a late cancellation means once money has changed hands. Worth noting that the cancellation policy the settings ship is a sentence you show, not a fee anything collects.

Two things, and both matter. Availability is worked out in Postgres from your opening hours, the length of the service, and every booking already confirmed or pending, so a taken slot is never offered, and it is worked out again inside the write, so a slot that went while somebody was typing is refused rather than sold twice. Then the hold: starting a booking takes the slot out of circulation for a set number of minutes, fifteen by default. Releasing an expired hold is the job you publish as a separate Scheduled deployment, and the check worth asking the Agent to demonstrate is the race: two bookings for one slot at the same moment, with one refused.

Yes, and it is one of the more carefully built parts of the template. A guest books with a name and an email address. A long random token with an expiry is generated for that booking, and finding it again means presenting the token, the email address, and the booking together. Every attempt is logged and lookups are rate-limited. Keep an eye on where that rate limit lives: a counter held in one process’s memory resets when a new instance starts, so on a deployment that can run more than one, move it somewhere shared.

No. The tables, the sessions, the access rules, the availability function, the server routes behind them, the guest token lookup, and the sweep that releases abandoned holds all get written from plain-language prompts, and the Postgres they write into is created inside this workspace when you ask. Nothing needs opening anywhere else first, though sign-in is worth a specific question, since this workspace provides the database without a hosted identity service to go with it.

The template ships one calendar, with each service carrying its own opening hours over your business defaults, which covers a solo practitioner and a small shop where anybody can do anything. A diary per staff member, or a room that can only host one appointment at a time, is a described change to the availability function rather than a rebuild, and it is worth deciding before you load your real services: whether a slot belongs to the business or to a particular person is the one structural question this application asks.

Yes. There is a cart, and a booking carries a list of services with the durations chosen, so a cut and a colour become one appointment long enough for both rather than two bookings that happen to be adjacent. That is a genuinely useful thing to have already built, because the arithmetic (one slot long enough for the total, checked against your opening hours) is the part people get wrong when they add it later.

Every appointment is stored as an absolute moment, and the screens draw it in the viewer’s local time, which is the right shape. What still needs your attention is testing it: open your own booking page with your computer set to another time zone and check that the slot you picked is the slot that shows up, and do the same around a clock change if your trade runs early or late. Almost every booking bug that reaches production is a time bug, and none of them are hard once you have looked.

Only somebody with a finished appointment of their own, and that rule lives in the database rather than in the form. The insert is checked against a booking belonging to that customer, so no screen can bypass it. You moderate what appears from the admin panel. The reason to care about where the rule lives is that a service page carrying ratings is worth something to strangers who want to post on it.

Your Replit plan, plus what you publish. Core starts at $25/month, or $20/month billed annually, and includes 20GB of Postgres. Services, bookings, and customers are small, and the photographs of what you offer are the part that grows. Publishing is billed separately on top, and this build publishes twice: the app itself, and the hold sweep as its own Scheduled deployment. Nothing scales with how many staff you have or how many appointments you take, and if you add an AI feature you pay whichever model you call for the text you send it.

Nothing here is proprietary. Replit provisions ordinary PostgreSQL, so a standard dump gives you your services, bookings, customers, and reviews in a form any Postgres host accepts, and the service photographs are ordinary files in object storage. That is worth more than it sounds in this category: your calendar is the record of your business, and it is exactly the thing that makes a platform expensive to leave.

Yes, and it is worth doing before you print the address anywhere. The replit.app subdomain the app starts on can be replaced with your own through Publishing, HTTPS included, and a booking page on your own domain is the difference between sending customers to you and sending them to a page with somebody else’s name above yours. Do it before the links go into your reply templates, your invoices, and the sign in your window.

No. You describe what you want in the chat, and the Agent handles the rest: the code, the database, and a live version of the app right there in the workspace. The setup section above covers the account and plan you need first.

Replit hosts it. Publishing takes the same project live on a Replit domain, or your own if you connect one, with monitoring and access controls included, so you never open a separate hosting account.

Starter’s daily credits and a paid plan’s monthly grant both refill on their own schedule. Hitting either limit mid-build doesn’t touch what you’ve already made. Move up a plan for more headroom right away, or wait it out.

References

Sources checked August 2026
  1. 01No-show rates before and after a scheduling intervention (JMIR Formative Research, January 2025). pmc.ncbi.nlm.nih.gov (study published January 2025)
  2. 02No-show fees in medical practices (MGMA Stat poll, 622 responses, January 2025). mgma.com (published January 2025)
  3. 03Patient digital self-scheduling adoption (MGMA Stat poll, 244 responses, July 2025). mgma.com (published July 2025)
  4. 04Pricing (per-seat tiers, free-tier event-type limit), Calendly. calendly.com
  5. 05Pricing (per-calendar tiers, both billing bases, trial), Acuity Scheduling. acuityscheduling.com
  6. 06Features (reminders, calendar sync, deposits at booking), Acuity Scheduling. acuityscheduling.com
  7. 07Pricing (monthly booking caps, custom-feature caps), SimplyBook.me. simplybook.me
  8. 08Pricing (free tier appointment cap, Pro per user), Setmore. setmore.com
  9. 09Pricing (Pro plan, free-tier limits, project pausing), Supabase. supabase.com
  10. 10Web developer hourly rates 2026 (freelance and agency benchmarks). developex.com
  11. 11Pricing (Starter, Core, Pro), Replit. replit.com
  12. 12Built-in database, Replit docs. docs.replit.com
  13. 13Publishing overview, Replit docs. docs.replit.com
  14. 14Deployment types, Replit docs. docs.replit.com
  15. 15Checkpoints and rollbacks, Replit docs. docs.replit.com
  16. 16Using the Git pane, Replit docs. docs.replit.com
  17. 17Import from a provider, Replit docs. docs.replit.com
  18. 18Secrets, Replit docs. docs.replit.com

This guide is general information, not legal advice. What you may keep about a customer, how long you may keep a record of where they were, and whether you may charge for a missed appointment vary by country and by state, so check your own rules before you collect anything or write a fee into a policy. 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. Replit is a product of Replit, Inc. Verify current capabilities and pricing before relying on them.