Booking form template
Date, time, how many people and the occasion — a reservation request for a table, a room or a venue.
Reviewed by Ritu Fadadu · Last reviewed
Preview and code
Preview
Code — replace YOUR_ENDPOINT_ID with your form's ID
<style>
.fb-form { display: grid; gap: 1rem; max-width: 36rem; }
.fb-field { display: flex; flex-direction: column; gap: 0.375rem; }
.fb-fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
.fb-label { font-weight: 600; }
.fb-optional { font-weight: 400; color: #6b7280; }
.fb-help { margin: 0; font-size: 0.875rem; color: #6b7280; }
.fb-input { box-sizing: border-box; width: 100%; padding: 0.625rem 0.75rem; border: 1px solid #d1d5db; border-radius: 0.5rem; background: #fff; color: #111827; font: inherit; }
.fb-input:focus { border-color: #2563eb; outline: 2px solid #2563eb; outline-offset: 1px; }
.fb-options { display: flex; flex-direction: column; gap: 0.5rem; }
.fb-option { display: flex; align-items: center; gap: 0.5rem; }
.fb-check { width: 1.125rem; height: 1.125rem; margin: 0; accent-color: #2563eb; }
.fb-button { justify-self: start; min-height: 44px; padding: 0.625rem 1.25rem; border: 0; border-radius: 0.5rem; background: #2563eb; color: #fff; font: inherit; font-weight: 600; cursor: pointer; }
.fb-button:hover { background: #1d4ed8; }
.fb-button:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; }
.fb-button:disabled { opacity: 0.6; cursor: wait; }
.fb-status { margin: 0; min-height: 1.5em; }
@media (min-width: 640px) {
.fb-form { grid-template-columns: 1fr 1fr; }
.fb-field, .fb-button, .fb-status { grid-column: 1 / -1; }
.fb-field--half { grid-column: auto; }
}
</style>
<form id="fb-form" class="fb-form" action="https://formboost.app/f/YOUR_ENDPOINT_ID" method="POST">
<div class="fb-field fb-field--half">
<label for="fb-name" class="fb-label">Name</label>
<input type="text" id="fb-name" name="name" class="fb-input" required autocomplete="name">
</div>
<div class="fb-field fb-field--half">
<label for="fb-email" class="fb-label">Email</label>
<input type="email" id="fb-email" name="email" class="fb-input" required autocomplete="email">
</div>
<div class="fb-field fb-field--half">
<label for="fb-phone" class="fb-label">Phone</label>
<input type="tel" id="fb-phone" name="phone" class="fb-input" required autocomplete="tel">
</div>
<div class="fb-field fb-field--half">
<label for="fb-guests" class="fb-label">Number of guests</label>
<input type="number" id="fb-guests" name="guests" class="fb-input" required min="1" max="20">
</div>
<div class="fb-field fb-field--half">
<label for="fb-date" class="fb-label">Date</label>
<input type="date" id="fb-date" name="date" class="fb-input" required>
</div>
<div class="fb-field fb-field--half">
<label for="fb-time" class="fb-label">Time</label>
<input type="time" id="fb-time" name="time" class="fb-input" required>
</div>
<div class="fb-field">
<label for="fb-occasion" class="fb-label">
Occasion
<span class="fb-optional">(optional)</span>
</label>
<select id="fb-occasion" name="occasion" class="fb-input">
<option value="">Choose…</option>
<option value="no-special-occasion">No special occasion</option>
<option value="birthday">Birthday</option>
<option value="anniversary">Anniversary</option>
<option value="business">Business</option>
<option value="other">Other</option>
</select>
</div>
<div class="fb-field">
<label for="fb-requests" class="fb-label">
Special requests
<span class="fb-optional">(optional)</span>
</label>
<textarea
id="fb-requests"
name="requests"
class="fb-input"
aria-describedby="fb-requests-help"
rows="3"
></textarea>
<p id="fb-requests-help" class="fb-help">
Accessibility needs, dietary requirements, seating preferences.
</p>
</div>
<!-- Honeypot: keep it hidden. People never see it; bots fill it in and get flagged as spam. -->
<div
aria-hidden="true"
style="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden"
>
<label for="fb-honey">Leave this field empty</label>
<input type="text" id="fb-honey" name="_honey" tabindex="-1" autocomplete="off">
</div>
<input type="hidden" name="_subject" value="New booking request">
<button type="submit" class="fb-button">Request booking</button>
</form>
<style>
.fb-form { display: grid; gap: 1rem; max-width: 36rem; }
.fb-field { display: flex; flex-direction: column; gap: 0.375rem; }
.fb-fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
.fb-label { font-weight: 600; }
.fb-optional { font-weight: 400; color: #6b7280; }
.fb-help { margin: 0; font-size: 0.875rem; color: #6b7280; }
.fb-input { box-sizing: border-box; width: 100%; padding: 0.625rem 0.75rem; border: 1px solid #d1d5db; border-radius: 0.5rem; background: #fff; color: #111827; font: inherit; }
.fb-input:focus { border-color: #2563eb; outline: 2px solid #2563eb; outline-offset: 1px; }
.fb-options { display: flex; flex-direction: column; gap: 0.5rem; }
.fb-option { display: flex; align-items: center; gap: 0.5rem; }
.fb-check { width: 1.125rem; height: 1.125rem; margin: 0; accent-color: #2563eb; }
.fb-button { justify-self: start; min-height: 44px; padding: 0.625rem 1.25rem; border: 0; border-radius: 0.5rem; background: #2563eb; color: #fff; font: inherit; font-weight: 600; cursor: pointer; }
.fb-button:hover { background: #1d4ed8; }
.fb-button:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; }
.fb-button:disabled { opacity: 0.6; cursor: wait; }
.fb-status { margin: 0; min-height: 1.5em; }
@media (min-width: 640px) {
.fb-form { grid-template-columns: 1fr 1fr; }
.fb-field, .fb-button, .fb-status { grid-column: 1 / -1; }
.fb-field--half { grid-column: auto; }
}
</style>
<form id="fb-form" class="fb-form" action="https://formboost.app/f/YOUR_ENDPOINT_ID" method="POST">
<div class="fb-field fb-field--half">
<label for="fb-name" class="fb-label">Name</label>
<input type="text" id="fb-name" name="name" class="fb-input" required autocomplete="name">
</div>
<div class="fb-field fb-field--half">
<label for="fb-email" class="fb-label">Email</label>
<input type="email" id="fb-email" name="email" class="fb-input" required autocomplete="email">
</div>
<div class="fb-field fb-field--half">
<label for="fb-phone" class="fb-label">Phone</label>
<input type="tel" id="fb-phone" name="phone" class="fb-input" required autocomplete="tel">
</div>
<div class="fb-field fb-field--half">
<label for="fb-guests" class="fb-label">Number of guests</label>
<input type="number" id="fb-guests" name="guests" class="fb-input" required min="1" max="20">
</div>
<div class="fb-field fb-field--half">
<label for="fb-date" class="fb-label">Date</label>
<input type="date" id="fb-date" name="date" class="fb-input" required>
</div>
<div class="fb-field fb-field--half">
<label for="fb-time" class="fb-label">Time</label>
<input type="time" id="fb-time" name="time" class="fb-input" required>
</div>
<div class="fb-field">
<label for="fb-occasion" class="fb-label">
Occasion
<span class="fb-optional">(optional)</span>
</label>
<select id="fb-occasion" name="occasion" class="fb-input">
<option value="">Choose…</option>
<option value="no-special-occasion">No special occasion</option>
<option value="birthday">Birthday</option>
<option value="anniversary">Anniversary</option>
<option value="business">Business</option>
<option value="other">Other</option>
</select>
</div>
<div class="fb-field">
<label for="fb-requests" class="fb-label">
Special requests
<span class="fb-optional">(optional)</span>
</label>
<textarea
id="fb-requests"
name="requests"
class="fb-input"
aria-describedby="fb-requests-help"
rows="3"
></textarea>
<p id="fb-requests-help" class="fb-help">
Accessibility needs, dietary requirements, seating preferences.
</p>
</div>
<!-- Honeypot: keep it hidden. People never see it; bots fill it in and get flagged as spam. -->
<div
aria-hidden="true"
style="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden"
>
<label for="fb-honey">Leave this field empty</label>
<input type="text" id="fb-honey" name="_honey" tabindex="-1" autocomplete="off">
</div>
<input type="hidden" name="_subject" value="New booking request">
<button type="submit" class="fb-button">Request booking</button>
<p class="fb-status" role="status" aria-live="polite" data-fb-status></p>
</form>
<script>
document.getElementById("fb-form").addEventListener("submit", async (event) => {
event.preventDefault();
const form = event.currentTarget;
const status = form.querySelector("[data-fb-status]");
const button = form.querySelector('button[type="submit"]');
const fields = new FormData(form);
// Formboost accepts JSON or url-encoded bodies, not multipart, so send JSON.
const data = Object.fromEntries(fields);
// Makes the notification email replyable; the address still shows in the field table.
if (data.email) data._replyto = data.email;
button.disabled = true;
status.textContent = "Sending…";
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(data),
});
if (response.ok) {
form.reset();
status.textContent = "Thanks — we'll confirm your booking by email.";
} else if (response.status === 429) {
status.textContent = "Too many attempts. Please wait a minute and try again.";
} else {
status.textContent = "Something went wrong. Please try again.";
}
} catch {
status.textContent = "Could not send. Check your connection and try again.";
} finally {
button.disabled = false;
}
});
</script>
import { useState } from "react";
// Your form's endpoint, from the Formboost dashboard.
const ENDPOINT = "https://formboost.app/f/YOUR_ENDPOINT_ID";
export default function BookingForm() {
const [sending, setSending] = useState(false);
const [message, setMessage] = useState("");
async function handleSubmit(event) {
event.preventDefault();
const form = event.currentTarget;
const fields = new FormData(form);
// Formboost accepts JSON or url-encoded bodies, not multipart, so send JSON.
const data = Object.fromEntries(fields);
// Makes the notification email replyable; the address still shows in the field table.
if (data.email) data._replyto = data.email;
setSending(true);
setMessage("Sending…");
try {
const response = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(data),
});
if (response.ok) {
form.reset();
setMessage("Thanks — we'll confirm your booking by email.");
} else if (response.status === 429) {
setMessage("Too many attempts. Please wait a minute and try again.");
} else {
setMessage("Something went wrong. Please try again.");
}
} catch {
setMessage("Could not send. Check your connection and try again.");
} finally {
setSending(false);
}
}
return (
<form
className="grid max-w-xl gap-4 sm:grid-cols-2"
action={ENDPOINT}
method="POST"
onSubmit={handleSubmit}
>
<div className="flex flex-col gap-1.5">
<label htmlFor="fb-name" className="text-sm font-semibold text-gray-900">Name</label>
<input
type="text"
id="fb-name"
name="name"
className="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
autoComplete="name"
/>
</div>
<div className="flex flex-col gap-1.5">
<label htmlFor="fb-email" className="text-sm font-semibold text-gray-900">Email</label>
<input
type="email"
id="fb-email"
name="email"
className="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
autoComplete="email"
/>
</div>
<div className="flex flex-col gap-1.5">
<label htmlFor="fb-phone" className="text-sm font-semibold text-gray-900">Phone</label>
<input
type="tel"
id="fb-phone"
name="phone"
className="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
autoComplete="tel"
/>
</div>
<div className="flex flex-col gap-1.5">
<label htmlFor="fb-guests" className="text-sm font-semibold text-gray-900">
Number of guests
</label>
<input
type="number"
id="fb-guests"
name="guests"
className="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
min="1"
max="20"
/>
</div>
<div className="flex flex-col gap-1.5">
<label htmlFor="fb-date" className="text-sm font-semibold text-gray-900">Date</label>
<input
type="date"
id="fb-date"
name="date"
className="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
/>
</div>
<div className="flex flex-col gap-1.5">
<label htmlFor="fb-time" className="text-sm font-semibold text-gray-900">Time</label>
<input
type="time"
id="fb-time"
name="time"
className="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
/>
</div>
<div className="flex flex-col gap-1.5 sm:col-span-2">
<label htmlFor="fb-occasion" className="text-sm font-semibold text-gray-900">
Occasion
<span className="font-normal text-gray-500">(optional)</span>
</label>
<select
id="fb-occasion"
name="occasion"
className="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
>
<option value="">Choose…</option>
<option value="no-special-occasion">No special occasion</option>
<option value="birthday">Birthday</option>
<option value="anniversary">Anniversary</option>
<option value="business">Business</option>
<option value="other">Other</option>
</select>
</div>
<div className="flex flex-col gap-1.5 sm:col-span-2">
<label htmlFor="fb-requests" className="text-sm font-semibold text-gray-900">
Special requests
<span className="font-normal text-gray-500">(optional)</span>
</label>
<textarea
id="fb-requests"
name="requests"
className="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
aria-describedby="fb-requests-help"
rows={3}
></textarea>
<p id="fb-requests-help" className="text-sm text-gray-500">
Accessibility needs, dietary requirements, seating preferences.
</p>
</div>
{/* Honeypot: keep it hidden. People never see it; bots fill it in and get flagged as spam. */}
<div
aria-hidden="true"
style={{ position: "absolute", left: "-9999px", width: "1px", height: "1px", overflow: "hidden" }}
>
<label htmlFor="fb-honey">Leave this field empty</label>
<input type="text" id="fb-honey" name="_honey" tabIndex={-1} autoComplete="off" />
</div>
<input type="hidden" name="_subject" defaultValue="New booking request" />
<button
type="submit"
className="min-h-11 justify-self-start rounded-lg bg-blue-600 px-5 py-2.5 font-semibold text-white hover:bg-blue-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 disabled:opacity-60 sm:col-span-2"
disabled={sending}
>
Request booking
</button>
<p className="min-h-6 text-sm text-gray-700 sm:col-span-2" role="status" aria-live="polite">
{message}
</p>
</form>
);
}
<form
id="fb-form"
class="grid max-w-xl gap-4 sm:grid-cols-2"
action="https://formboost.app/f/YOUR_ENDPOINT_ID"
method="POST"
>
<div class="flex flex-col gap-1.5">
<label for="fb-name" class="text-sm font-semibold text-gray-900">Name</label>
<input
type="text"
id="fb-name"
name="name"
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
autocomplete="name"
>
</div>
<div class="flex flex-col gap-1.5">
<label for="fb-email" class="text-sm font-semibold text-gray-900">Email</label>
<input
type="email"
id="fb-email"
name="email"
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
autocomplete="email"
>
</div>
<div class="flex flex-col gap-1.5">
<label for="fb-phone" class="text-sm font-semibold text-gray-900">Phone</label>
<input
type="tel"
id="fb-phone"
name="phone"
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
autocomplete="tel"
>
</div>
<div class="flex flex-col gap-1.5">
<label for="fb-guests" class="text-sm font-semibold text-gray-900">Number of guests</label>
<input
type="number"
id="fb-guests"
name="guests"
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
min="1"
max="20"
>
</div>
<div class="flex flex-col gap-1.5">
<label for="fb-date" class="text-sm font-semibold text-gray-900">Date</label>
<input
type="date"
id="fb-date"
name="date"
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
>
</div>
<div class="flex flex-col gap-1.5">
<label for="fb-time" class="text-sm font-semibold text-gray-900">Time</label>
<input
type="time"
id="fb-time"
name="time"
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
required
>
</div>
<div class="flex flex-col gap-1.5 sm:col-span-2">
<label for="fb-occasion" class="text-sm font-semibold text-gray-900">
Occasion
<span class="font-normal text-gray-500">(optional)</span>
</label>
<select
id="fb-occasion"
name="occasion"
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
>
<option value="">Choose…</option>
<option value="no-special-occasion">No special occasion</option>
<option value="birthday">Birthday</option>
<option value="anniversary">Anniversary</option>
<option value="business">Business</option>
<option value="other">Other</option>
</select>
</div>
<div class="flex flex-col gap-1.5 sm:col-span-2">
<label for="fb-requests" class="text-sm font-semibold text-gray-900">
Special requests
<span class="font-normal text-gray-500">(optional)</span>
</label>
<textarea
id="fb-requests"
name="requests"
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-gray-900 focus:border-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600/30"
aria-describedby="fb-requests-help"
rows="3"
></textarea>
<p id="fb-requests-help" class="text-sm text-gray-500">
Accessibility needs, dietary requirements, seating preferences.
</p>
</div>
<!-- Honeypot: keep it hidden. People never see it; bots fill it in and get flagged as spam. -->
<div
aria-hidden="true"
style="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden"
>
<label for="fb-honey">Leave this field empty</label>
<input type="text" id="fb-honey" name="_honey" tabindex="-1" autocomplete="off">
</div>
<input type="hidden" name="_subject" value="New booking request">
<button
type="submit"
class="min-h-11 justify-self-start rounded-lg bg-blue-600 px-5 py-2.5 font-semibold text-white hover:bg-blue-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 disabled:opacity-60 sm:col-span-2"
>
Request booking
</button>
</form>
About this template
This template is for reservations: a restaurant table, a meeting room, a studio, a venue. It asks for the date, the time, the number of guests and the occasion, and leaves room for special requests. It is a request — it does not check availability — so you reply to confirm, or to suggest another time.
The guest count is a number field with sensible limits, so a phone shows a number pad and nobody books for zero. The occasion is optional, but it is the field that lets you put a candle on the cake or the right sign on the door.
If you take appointments with a person rather than bookings for a space, the appointment request template asks for a service and a second-choice time instead.
Fields in this template
| Field | Name | Type | Required | Why it is there |
|---|---|---|---|---|
| Name | name | Short text | Yes | Required — the name on the booking. |
email | Yes | Required, for the confirmation. | ||
| Phone | phone | Phone | Yes | Required, for same-day changes. |
| Number of guests | guests | Number | Yes | Required number, 1 to 20. |
| Date | date | Date | Yes | Required native date picker. |
| Time | time | Time | Yes | Required native time picker. |
| Occasion | occasion | Dropdown | No | Optional, and the detail guests remember. |
| Special requests | requests | Long text | No | Optional notes for planning. |
Each name becomes a column in your dashboard and a row in the notification email. The hidden _honey field is the honeypot; _subject sets the email's subject line. Both are reserved fields and never appear in the field table.
Make it yours
- Raise the guest
maxfor venues, or replace it with ranges for large events. - List your opening hours next to the form; the time picker does not know them.
- Add a
deposit_okcheckbox if large parties pay a deposit you collect separately. - Add a
seatingsingle-choice question (inside, outside, no preference) if you have a terrace — it is the most common special request. - Say above the form how far ahead you take bookings; the date picker will happily accept a date next year.
Where the submissions go
- Each booking request is stored and emailed to you; reply to confirm.
- Get bookings on your phone with Telegram, on any plan, so you can confirm while it is still convenient for the guest.
- On Starter and above, Auto Reply acknowledges the request instantly, and a webhook can add it to your reservation system.
Before you publish it
- Create a form in the Formboost dashboard and replace
YOUR_ENDPOINT_IDwith its ID. - Pick one variant: HTML posts and reloads, HTML + JS and React send JSON with
fetch()and stay on the page. - For the plain HTML version, add a hidden
_redirectwith anhttps://thank-you page on the same site as the form — anything else falls back to Formboost's page. - Submit it once from the live page and check the submission in your dashboard. Every request is acknowledged, so the dashboard is the real test. Troubleshooting covers the rest.
More form templates
Appointment request form template
A preferred date and time, a second choice and the reason for the visit — a request you confirm, not a calendar.
RSVP form template
Yes or no, how many are coming, meal choice and a note for the hosts.
Order form template
Product, quantity, delivery or collection — an order request you confirm and invoice.
All form templates
Every template, in HTML, React and Tailwind.
Put the booking form live
Free forever: 500 submissions a month across 10 forms, no card.