RSVP form template
Yes or no, how many are coming, meal choice and a note for the hosts.
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">Your 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>
<fieldset class="fb-field fb-fieldset">
<legend class="fb-label">Will you be there?</legend>
<div class="fb-options">
<label class="fb-option">
<input type="radio" name="attending" value="yes-i-ll-be-there" class="fb-check" required>
<span>Yes, I'll be there</span>
</label>
<label class="fb-option">
<input
type="radio"
name="attending"
value="sorry-i-can-t-make-it"
class="fb-check"
required
>
<span>Sorry, I can't make it</span>
</label>
</div>
</fieldset>
<div class="fb-field fb-field--half">
<label for="fb-guests" class="fb-label">
Guests coming with you
<span class="fb-optional">(optional)</span>
</label>
<input
type="number"
id="fb-guests"
name="guests"
class="fb-input"
aria-describedby="fb-guests-help"
min="0"
max="5"
>
<p id="fb-guests-help" class="fb-help">Not counting yourself.</p>
</div>
<div class="fb-field fb-field--half">
<label for="fb-meal" class="fb-label">
Meal choice
<span class="fb-optional">(optional)</span>
</label>
<select id="fb-meal" name="meal" class="fb-input">
<option value="">Choose…</option>
<option value="meat">Meat</option>
<option value="fish">Fish</option>
<option value="vegetarian">Vegetarian</option>
<option value="vegan">Vegan</option>
</select>
</div>
<div class="fb-field">
<label for="fb-dietary" class="fb-label">
Allergies or dietary needs
<span class="fb-optional">(optional)</span>
</label>
<input type="text" id="fb-dietary" name="dietary" class="fb-input">
</div>
<div class="fb-field">
<label for="fb-note" class="fb-label">
A note for the hosts
<span class="fb-optional">(optional)</span>
</label>
<textarea id="fb-note" name="note" class="fb-input" rows="3"></textarea>
</div>
<input type="hidden" name="event" value="summer-party-2026">
<!-- 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 RSVP">
<button type="submit" class="fb-button">Send RSVP</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">Your 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>
<fieldset class="fb-field fb-fieldset">
<legend class="fb-label">Will you be there?</legend>
<div class="fb-options">
<label class="fb-option">
<input type="radio" name="attending" value="yes-i-ll-be-there" class="fb-check" required>
<span>Yes, I'll be there</span>
</label>
<label class="fb-option">
<input
type="radio"
name="attending"
value="sorry-i-can-t-make-it"
class="fb-check"
required
>
<span>Sorry, I can't make it</span>
</label>
</div>
</fieldset>
<div class="fb-field fb-field--half">
<label for="fb-guests" class="fb-label">
Guests coming with you
<span class="fb-optional">(optional)</span>
</label>
<input
type="number"
id="fb-guests"
name="guests"
class="fb-input"
aria-describedby="fb-guests-help"
min="0"
max="5"
>
<p id="fb-guests-help" class="fb-help">Not counting yourself.</p>
</div>
<div class="fb-field fb-field--half">
<label for="fb-meal" class="fb-label">
Meal choice
<span class="fb-optional">(optional)</span>
</label>
<select id="fb-meal" name="meal" class="fb-input">
<option value="">Choose…</option>
<option value="meat">Meat</option>
<option value="fish">Fish</option>
<option value="vegetarian">Vegetarian</option>
<option value="vegan">Vegan</option>
</select>
</div>
<div class="fb-field">
<label for="fb-dietary" class="fb-label">
Allergies or dietary needs
<span class="fb-optional">(optional)</span>
</label>
<input type="text" id="fb-dietary" name="dietary" class="fb-input">
</div>
<div class="fb-field">
<label for="fb-note" class="fb-label">
A note for the hosts
<span class="fb-optional">(optional)</span>
</label>
<textarea id="fb-note" name="note" class="fb-input" rows="3"></textarea>
</div>
<input type="hidden" name="event" value="summer-party-2026">
<!-- 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 RSVP">
<button type="submit" class="fb-button">Send RSVP</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 for letting us know!";
} 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 RSVPForm() {
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 for letting us know!");
} 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">Your 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>
<fieldset className="flex flex-col gap-1.5 sm:col-span-2 m-0 min-w-0 border-0 p-0">
<legend className="text-sm font-semibold text-gray-900">Will you be there?</legend>
<div className="flex flex-col gap-2">
<label className="flex items-center gap-2 text-gray-800">
<input
type="radio"
name="attending"
value="yes-i-ll-be-there"
className="h-4 w-4 accent-blue-600"
required
/>
<span>Yes, I'll be there</span>
</label>
<label className="flex items-center gap-2 text-gray-800">
<input
type="radio"
name="attending"
value="sorry-i-can-t-make-it"
className="h-4 w-4 accent-blue-600"
required
/>
<span>Sorry, I can't make it</span>
</label>
</div>
</fieldset>
<div className="flex flex-col gap-1.5">
<label htmlFor="fb-guests" className="text-sm font-semibold text-gray-900">
Guests coming with you
<span className="font-normal text-gray-500">(optional)</span>
</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"
aria-describedby="fb-guests-help"
min="0"
max="5"
/>
<p id="fb-guests-help" className="text-sm text-gray-500">Not counting yourself.</p>
</div>
<div className="flex flex-col gap-1.5">
<label htmlFor="fb-meal" className="text-sm font-semibold text-gray-900">
Meal choice
<span className="font-normal text-gray-500">(optional)</span>
</label>
<select
id="fb-meal"
name="meal"
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="meat">Meat</option>
<option value="fish">Fish</option>
<option value="vegetarian">Vegetarian</option>
<option value="vegan">Vegan</option>
</select>
</div>
<div className="flex flex-col gap-1.5 sm:col-span-2">
<label htmlFor="fb-dietary" className="text-sm font-semibold text-gray-900">
Allergies or dietary needs
<span className="font-normal text-gray-500">(optional)</span>
</label>
<input
type="text"
id="fb-dietary"
name="dietary"
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"
/>
</div>
<div className="flex flex-col gap-1.5 sm:col-span-2">
<label htmlFor="fb-note" className="text-sm font-semibold text-gray-900">
A note for the hosts
<span className="font-normal text-gray-500">(optional)</span>
</label>
<textarea
id="fb-note"
name="note"
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"
rows={3}
></textarea>
</div>
<input type="hidden" name="event" defaultValue="summer-party-2026" />
{/* 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 RSVP" />
<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}
>
Send RSVP
</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">Your 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>
<fieldset class="flex flex-col gap-1.5 sm:col-span-2 m-0 min-w-0 border-0 p-0">
<legend class="text-sm font-semibold text-gray-900">Will you be there?</legend>
<div class="flex flex-col gap-2">
<label class="flex items-center gap-2 text-gray-800">
<input
type="radio"
name="attending"
value="yes-i-ll-be-there"
class="h-4 w-4 accent-blue-600"
required
>
<span>Yes, I'll be there</span>
</label>
<label class="flex items-center gap-2 text-gray-800">
<input
type="radio"
name="attending"
value="sorry-i-can-t-make-it"
class="h-4 w-4 accent-blue-600"
required
>
<span>Sorry, I can't make it</span>
</label>
</div>
</fieldset>
<div class="flex flex-col gap-1.5">
<label for="fb-guests" class="text-sm font-semibold text-gray-900">
Guests coming with you
<span class="font-normal text-gray-500">(optional)</span>
</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"
aria-describedby="fb-guests-help"
min="0"
max="5"
>
<p id="fb-guests-help" class="text-sm text-gray-500">Not counting yourself.</p>
</div>
<div class="flex flex-col gap-1.5">
<label for="fb-meal" class="text-sm font-semibold text-gray-900">
Meal choice
<span class="font-normal text-gray-500">(optional)</span>
</label>
<select
id="fb-meal"
name="meal"
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="meat">Meat</option>
<option value="fish">Fish</option>
<option value="vegetarian">Vegetarian</option>
<option value="vegan">Vegan</option>
</select>
</div>
<div class="flex flex-col gap-1.5 sm:col-span-2">
<label for="fb-dietary" class="text-sm font-semibold text-gray-900">
Allergies or dietary needs
<span class="font-normal text-gray-500">(optional)</span>
</label>
<input
type="text"
id="fb-dietary"
name="dietary"
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"
>
</div>
<div class="flex flex-col gap-1.5 sm:col-span-2">
<label for="fb-note" class="text-sm font-semibold text-gray-900">
A note for the hosts
<span class="font-normal text-gray-500">(optional)</span>
</label>
<textarea
id="fb-note"
name="note"
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"
rows="3"
></textarea>
</div>
<input type="hidden" name="event" value="summer-party-2026">
<!-- 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 RSVP">
<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"
>
Send RSVP
</button>
</form>
About this template
An RSVP form answers one question first: are you coming? The attending choice is the only required field besides name and email, and its two options are written as sentences — “Yes, I'll be there” and “Sorry, I can't make it” — so nobody has to think about which button means what.
The guest count asks for people in addition to the person replying, with the help text saying so. That single sentence prevents the most common RSVP mistake: a couple replying “2” and being counted as three.
Meal choice and dietary needs are optional, because people who are not coming will skip them. A hidden event field names the event, so one form can serve a wedding weekend's several events, or this year's party and next year's.
Fields in this template
| Field | Name | Type | Required | Why it is there |
|---|---|---|---|---|
| Your name | name | Short text | Yes | Required. |
email | Yes | Required, for updates and a confirmation. | ||
| Will you be there? | attending | Single choice | Yes | Required. Two options written as sentences. |
| Guests coming with you | guests | Number | No | Optional number, 0 to 5, not counting the person replying. |
| Meal choice | meal | Dropdown | No | Optional dropdown for catering. |
| Allergies or dietary needs | dietary | Short text | No | Optional free text. |
| A note for the hosts | note | Long text | No | Optional — usually the nicest part of the replies. |
| (hidden) | event | Hidden value | No | Hidden. One form, several events. |
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
- Change the meal options to your caterer's menu, or remove the question for a drinks-only event.
- Raise the guest
max, or remove the field for a named-guests-only invitation. - Redirect to a page with the venue, the time and the dress code with a custom redirect.
- State a reply-by date above the form; the form itself stays open until you take it down.
- If you invite people in batches by email, add a hidden
invitevalue per batch to see which batch has not replied yet.
Where the submissions go
- Every reply is stored and emailed to you; export the guest list to CSV on every plan.
- On Starter and above, keep a live headcount in Google Sheets that the other hosts can see.
- Send each RSVP to a shared Telegram or Discord chat for the organisers, on any plan.
Event Registration: plans, destinations and a worked setup →
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
Event registration form template
Attendee details, how they will attend, and the two questions organisers always forget to ask.
Registration form template
Personal details, address, the course or programme, and agreement to the terms.
Booking form template
Date, time, how many people and the occasion — a reservation request for a table, a room or a venue.
All form templates
Every template, in HTML, React and Tailwind.
Put the rsvp form live
Free forever: 500 submissions a month across 10 forms, no card.