Skip to content

component

BookingPro

By MJ Jung

Details

Summary

BookingPro sends a clean JSON payload to Formspree or any webhook, so it slots straight into the workflow you already have: - Zapier / Make / n8n — Auto-send a confirmation email…

Description

A Calendly-style booking widget for Framer. Visitors pick a date and time on your own site and submit their details — fully branded, on your own domain, with no monthly subscription. Drop it in, paste your Formspree ID, optionally connect a Google Sheet that holds your taken slots, and you're live. - Calendly-style booking without the monthly fee. A polished date+time picker that lives on your own domain, with your own brand. One-time purchase instead of a per-seat subscription. - Friendly booking horizon. Pick "1 month from today", "3 months", "1 year" — no need to think in raw days. Calendar math is correct (1 month = the same day next month, not 30 days). - Pick your week start. Monday (Europe / ISO, default), Sunday (US), or Saturday (Middle East). The grid and weekday labels rotate automatically. - Four booking modes built in. Single appointment, multi-time block, hotel-style date range (check-in / check-out), or multiple independent dates. One component, all the use cases. - Three ways to know what's already taken. Edit the booked list right in Framer, or sync from a Google Sheet, or pull from any JSON URL. - Already-booked slots are visually clear. Taken slots are grayed out and show your custom message — no double bookings. - Truly customizable form. You decide which fields to ask: name, email, phone, project description, anything. - Sends straight to Formspree (or any webhook). The chosen date(s) and time(s) are added to the payload automatically. - Designer-first. Four ready-made presets (Modern, Minimal, Soft, Dark), every color editable, every label rewriteable. Korean / Japanese / Spanish weekday and month names just need a quick paste. - No code, no plugins, no CMS. No CMS dependency — booking data comes from your panel or a URL you choose. After purchase you'll receive a `.txt` file containing the component URL. To bring it into Framer: 1. Open the `.txt` file and copy the URL (Ctrl + C / Cmd + C). 2. Go to your Framer dashboard and open the project where you want to use it. 3. Click into the canvas. 4. Paste the URL directly onto the canvas (Ctrl + V / Cmd + V). Framer will detect the link and place the component on your page. Drag it, resize it, and configure it from the right-side property panel. Pick one in the Booking Mode dropdown at the top of the property panel. Classic Calendly-style. User picks a date, then one time slot. Best for: 1-on-1 calls, consultations, demos, photo shoots. User picks a date, then any number of time slots in that day. Optional Consecutive Only toggle requires the picked slots to be adjacent — perfect for "book a 2-hour studio block" or "book lunch + the meeting after". Hotel-style. User picks a start date (check-in), then an end date (check-out). The whole range highlights, the form summary shows the night count. Best for: lodging, multi-day rentals, conference room reservations. User picks any number of independent days. Best for: "select all the dates you're available", workshop signups with optional days, photo session day picker. The booked list works for all modes. In date-only modes (range / multi-date), any taken date in your sheet blocks that whole day. 1. Drop the component on your canvas. 2. Open the property panel on the right. 3. Availability — set your working days, hours, and slot length (e.g. Mon–Fri, 9–18, 30-minute slots). 4. Form Fields — add the questions you want to ask the visitor. 5. Submission — pick Formspree, paste your form ID. Done. Optional but powerful: set Existing Bookings → Source to Google Sheet and paste a published CSV URL so booked slots come straight from your spreadsheet. Every group below is a collapsible panel in the Framer property pane. - Style Preset — pick a look in one click (Modern / Minimal / Soft / Dark / Custom). - Availability — working days (1=Mon, 2=Tue…), hours, slot length, lunch break, holidays, timezone label. - Existing Bookings — pick how to sync taken slots: manual list, Google Sheet, or JSON URL. - Form Fields — add any number of fields with id, label, type, placeholder, and required flag. - Submission — Formspree ID, Webhook URL + Allowed Domains, email subject, the keys used for date/time in the payload. - Messages — every visible string. Translate to any language, change the booked-slot warning, the success message, the back/submit labels — anything. - Calendar Style — header, weekday labels, date colors, today ring, booked-slot dot color. - Slots Style — slot colors (default / hover / selected / booked), columns, padding, radius. - Form Style — input colors, label color, font sizes, spacing. - Buttons — primary and secondary button colors, radius, padding, weight. - Container — background, border, radius, summary pill, progress bar. Most designers only touch a few of these. Pick a preset, edit your fields, ship. You decide where the list of "already taken" times lives. Type slots into the property panel. Best for solo founders or low-volume use. Step 1 — Create the sheet. Open a new Google Sheet and add two column headers in the first row: `date` and `time`. Then list each booked slot as one row: | date | time | |------|------| | 2026-05-15 | 10:00 | | 2026-05-15 | 14:00 | | 2026-05-16 | 11:00 | Format rules: - date in `YYYY-MM-DD` format (e.g. `2026-05-15`) - time in 24-hour `HH:MM` format (e.g. `10:00`, `14:30`) - One booking per row Step 2 — Publish the sheet as CSV. In Google Sheets: 1. File → Share → Publish to web 2. Choose your sheet, format Comma-separated values (.csv), click Publish 3. Copy the URL Google gives you 4. Paste into the Sheet CSV URL field in the property panel The component re-checks the sheet on load (and optionally every N seconds). Add or remove a row in the sheet and the website updates without redeploying. Beautiful for a small team where someone manages bookings in Sheets. For date-only modes (Date Range / Multiple Dates): the `time` column is still required, but the value is ignored — you can put anything (e.g. `00:00`). One row per blocked day. For anyone with a backend or automation. Point it at any URL that returns JSON like: ```json [ { "date": "2026-05-15", "time": "10:00" }, { "date": "2026-05-15", "time": "14:00" } ] ``` or `{ "bookings": [...] }` or `{ "data": [...] }`. The component handles all three shapes. When a slot is already taken: - It appears grayed out in the time grid - The clickable behavior depends on Disable Booked Slots: - On (default): the slot can't be clicked at all - Off: clicking it shows your custom Booked Slot Message ("Sorry, this time is already taken — please pick another") You write the message in any language you want, with any tone. The default is friendly: "This slot is already taken. Please pick another time." When the user submits, the component sends a JSON `POST` to your endpoint with all the fields they filled in plus the chosen date and time. Endpoint: ` https://formspree.io/f/{your-form-id}` . You only paste the form ID (e.g. `xnqklbpr`) — not a full URL. The component builds the HTTPS endpoint for you. Any URL that accepts a JSON body — Zapier, Make, n8n, your own server, Notion via integrations, Airtable, Slack incoming webhooks. Two rules: 1. HTTPS only. ` http://` URLs are rejected. 2. List the allowed domains. In the Submission group, fill Allowed Domains with a comma-separated list of the hosts you trust, e.g. ` hooks.zapier.com , hook.us1.make.com , your-backend.com `. The component refuses to POST anywhere else. Subdomains count (so ` hook.us1.make.com ` covers `*. hook.us1.make.com ` as well). This keeps visitor data safe: if a webhook URL is ever changed by mistake (or by someone you didn't authorize), submissions won't silently leak to an unknown server. The exact keys depend on the Booking Mode you chose. Custom form field IDs always come through. Here are the extras the component adds automatically: Date + Single Time (default) ```json { "name": "Sarah Kim", "email": " sarah@example.com ", "date": "2026-05-15", "time": "14:00", "_subject": "New booking request" } ``` Date + Multiple Times ```json { "name": "Sarah Kim", "email": " sarah@example.com ", "date": "2026-05-15", "time": "14:00", "times": "14:00, 14:30, 15:00", "_subject": "..." } ``` Date Range (Check-in / Check-out) ```json { "name": "Sarah Kim", "email": " sarah@example.com ", "date": "2026-05-15", "checkOut": "2026-05-18", "nights": "3", "dates": "2026-05-15, 2026-05-16, 2026-05-17, 2026-05-18", "_subject": "..." } ``` Multiple Dates ```json { "name": "Sarah Kim", "email": " sarah@example.com ", "date": "2026-05-15", "dates": "2026-05-15, 2026-05-22, 2026-06-05", "_subject": "..." } ``` All key names (`date`, `time`, `checkOut`, `nights`, `dates`, `times`) are configurable in the Submission group, in case your tool expects different names. If your endpoint replies with a non-2xx status, the component shows your Error Message with a Back button so the user can try again. - 1-on-1 consultations and discovery calls - Coaching sessions and tutoring - Photo / video shoot booking - Studio / equipment rental - Salon / clinic appointments (with the holiday list filled in) - Hotels, B&Bs, and lodging with check-in / check-out (range mode) - Multi-day rentals and tour bookings - Workshop / class registration with optional days (multi-date mode) - Internal demos and sales calls - Real estate viewings - Anywhere you currently bounce between emails to schedule, or pay $10–30/month for a tool you barely use BookingPro sends a clean JSON payload to Formspree or any webhook, so it slots straight into the workflow you already have: - Zapier / Make / n8n — Auto-send a confirmation email to the visitor, push the booking into Google Sheets, create a Notion page, or message a Slack channel. - Google Calendar / Outlook — Add a Zapier step to create a calendar event the moment a booking lands. - Gmail / SendGrid / Resend — Trigger a branded confirmation email from your own address. - Stripe / PayPal — For paid bookings, wire the webhook to a payment link and unlock the calendar event after checkout. - Your own server — Point the webhook at any HTTPS endpoint that accepts a JSON `POST`. Total control. Because the data comes through as a regular `POST`, every "what if I want X to happen automatically" question has an answer. - For consultations, set Slot Length to 30 or 60 and keep Working Days to weekdays only. - If you allow same-day bookings, set Min Days Ahead to 0. To require a day's notice, set it to 1. - Use Holidays for fixed off-days (e.g. `2026-12-25, 2026-01-01`). - Korean labels: paste `1월, 2월, 3월, 4월, 5월, 6월, 7월, 8월, 9월, 10월, 11월, 12월` into Month Labels and `월, 화, 수, 목, 금, 토, 일` into Weekday Labels. - For Google Sheet sync, keep your sheet really simple — just `date` and `time` columns. Anything else is ignored. - Test once with Submission → Send To = None to walk through the flow without sending anything. If a submission isn't arriving, check that: - The Formspree ID is just the ID (e.g. `xnqklbpr`), not the full URL. - Formspree has confirmed your sender email (they email you once after the first submission). - Your webhook (if using one) is HTTPS and the host is listed in Allowed Domains (comma-separated, e.g. ` hooks.zapier.com , hook.us1.make.com `). - Your webhook responds with a 2xx status. If you see a red error banner on the Framer canvas: - That banner shows up only while you're designing — it's a heads-up that the Google Sheet / JSON URL didn't load. Visitors will never see it. - Click Retry to re-fetch without touching the property panel. - Common cause: the Sheet wasn't published as CSV, or the JSON URL returned a non-2xx status. If booked slots aren't grayed out: - The Sheet URL must be the published CSV URL (ends with `output=csv`), not the regular sheet URL. - The column headers in your sheet should match what you typed in Date Column and Time Column (default `date` and `time`). - Dates should be in `YYYY-MM-DD` format. The component also accepts `MM/DD/YYYY` and `YYYY/MM/DD` but `YYYY-MM-DD` is safest. Everything else works out of the box.

Introduction

Subscription-free Framer booking widget.

Rank history

Daily rank per list, from the first snapshot — lower is better.

120014001600163838/148/228/309/79/15
  • All · #3408