RSVP form you can copy
Describe your event in the box, for example “RSVP for a birthday dinner with a plus-one and a vegetarian option”, or edit the fields yourself. The HTML tab is selected. It works on a single rsvp.html page, GitHub Pages, Netlify or any site builder that takes custom HTML.
Fields, no AI
Live preview
Preview only. Nothing is sent from this page.
RSVP
Copy the code
Replace fk_your_access_key with your own Formgong access key. The placeholder does not accept submissions. The honeypot field is named botcheck. Leave it empty.
The HTML form posts in the browser. React and Vue show an error on the page if the request fails. These class names need Tailwind on your site. This page does not load Tailwind. Bootstrap 5 class names need Bootstrap on your site. This page does not load Bootstrap.
<style>
#fg-fk_your_access_key{box-sizing:border-box;max-width:520px;width:100%;padding:28px;border:1px solid #dbe2ea;border-radius:8px;background:#fff;color:#0f172a;font:16px/1.5 system-ui,sans-serif;display:grid;gap:16px}#fg-fk_your_access_key *{box-sizing:border-box}#fg-fk_your_access_key h2{font-size:24px;line-height:1.3;margin:0 0 4px;color:#0f172a}#fg-fk_your_access_key label{display:grid;gap:6px;font-weight:500}#fg-fk_your_access_key input,#fg-fk_your_access_key textarea,#fg-fk_your_access_key select{width:100%;font:inherit;min-height:44px;border:1px solid #94a3b8;border-radius:8px;padding:10px 12px;background:#fff;color:#0f172a}#fg-fk_your_access_key textarea{min-height:96px;resize:vertical}#fg-fk_your_access_key .fg-reminder-consent{display:flex;align-items:flex-start;gap:10px;font-weight:400}#fg-fk_your_access_key input[type=checkbox]{width:20px;min-height:20px;flex-shrink:0;margin:2px 0}#fg-fk_your_access_key button{font:inherit;font-weight:600;min-height:48px;padding:12px 20px;border:0;border-radius:8px;background:#4338ca;color:#ffffff;cursor:pointer}#fg-fk_your_access_key :focus-visible{outline:3px solid #4338ca;outline-offset:3px}#fg-fk_your_access_key button:disabled{cursor:wait;opacity:.7}#fg-fk_your_access_key p{margin:0}#fg-fk_your_access_key fieldset{border:0;padding:0;margin:0;display:grid;gap:8px;min-width:0}#fg-fk_your_access_key legend{font-weight:500;padding:0;margin-bottom:6px}#fg-fk_your_access_key .fg-choice{display:flex;align-items:center;gap:10px;font-weight:400}#fg-fk_your_access_key input[type=radio]{width:20px;min-height:20px;flex-shrink:0;margin:0}#fg-fk_your_access_key .fg-trap{position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
</style>
<form id="fg-fk_your_access_key" action="https://formgong.com/submit" method="POST">
<h2>RSVP</h2>
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="en">
<label>Your name * <input type="text" name="name" required autocomplete="name"></label>
<label>Email * <input type="email" name="email" required autocomplete="email"></label>
<fieldset><legend>Will you be there? *</legend><label class="fg-choice"><input type="radio" name="attending" value="Yes, I will be there" required> Yes, I will be there</label><label class="fg-choice"><input type="radio" name="attending" value="Sorry, I can't make it" required> Sorry, I can't make it</label></fieldset>
<label>How many people, including you? <input type="number" name="guests"></label>
<label>Meal choice <select name="meal"><option value="">—</option><option value="Meat">Meat</option><option value="Fish">Fish</option><option value="Vegetarian">Vegetarian</option><option value="Vegan">Vegan</option></select></label>
<label>Allergies or dietary needs <textarea name="dietary"></textarea></label>
<label>A note for the hosts <textarea name="note"></textarea></label>
<div class="fg-trap" aria-hidden="true"><label>Leave this field empty<input name="botcheck" tabindex="-1" autocomplete="off"></label></div>
<button type="submit">Send RSVP</button>
</form><form class="relative mx-auto grid w-full max-w-lg gap-4 rounded-lg border border-slate-200 bg-white p-6 text-base text-slate-900" action="https://formgong.com/submit" method="POST"> <h2 class="text-2xl font-semibold">RSVP</h2> <input type="hidden" name="access_key" value="fk_your_access_key"> <input type="hidden" name="_lang" value="en"> <div class="grid gap-1"><label class="font-medium" for="tw-name">Your name *</label><input class="w-full rounded-md border border-slate-400 bg-white px-3 py-2 text-base text-slate-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-700" id="tw-name" type="text" name="name" autocomplete="name" required></div> <div class="grid gap-1"><label class="font-medium" for="tw-email">Email *</label><input class="w-full rounded-md border border-slate-400 bg-white px-3 py-2 text-base text-slate-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-700" id="tw-email" type="email" name="email" autocomplete="email" required></div> <fieldset class="grid gap-2 border-0 p-0"><legend class="font-medium">Will you be there? *</legend><label class="flex items-center gap-2 font-normal" for="tw-attending-0"><input class="h-5 w-5" id="tw-attending-0" type="radio" name="attending" value="Yes, I will be there" required> Yes, I will be there</label><label class="flex items-center gap-2 font-normal" for="tw-attending-1"><input class="h-5 w-5" id="tw-attending-1" type="radio" name="attending" value="Sorry, I can't make it" required> Sorry, I can't make it</label></fieldset> <div class="grid gap-1"><label class="font-medium" for="tw-guests">How many people, including you?</label><input class="w-full rounded-md border border-slate-400 bg-white px-3 py-2 text-base text-slate-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-700" id="tw-guests" type="number" name="guests"></div> <div class="grid gap-1"><label class="font-medium" for="tw-meal">Meal choice</label><select class="w-full rounded-md border border-slate-400 bg-white px-3 py-2 text-base text-slate-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-700" id="tw-meal" name="meal"><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="grid gap-1"><label class="font-medium" for="tw-dietary">Allergies or dietary needs</label><textarea class="w-full rounded-md border border-slate-400 bg-white px-3 py-2 text-base text-slate-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-700 min-h-24" id="tw-dietary" name="dietary"></textarea></div> <div class="grid gap-1"><label class="font-medium" for="tw-note">A note for the hosts</label><textarea class="w-full rounded-md border border-slate-400 bg-white px-3 py-2 text-base text-slate-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-700 min-h-24" id="tw-note" name="note"></textarea></div> <div class="absolute start-0 top-0 h-px w-px overflow-hidden" aria-hidden="true"><label>Leave this empty<input name="botcheck" tabindex="-1" autocomplete="off"></label></div> <button class="min-h-12 rounded-md bg-indigo-700 px-4 py-3 font-semibold text-white" type="submit">Send RSVP</button> </form>
<form class="position-relative mx-auto" style="max-width:32rem" action="https://formgong.com/submit" method="POST"> <h2 class="h4 mb-3">RSVP</h2> <input type="hidden" name="access_key" value="fk_your_access_key"> <input type="hidden" name="_lang" value="en"> <div class="mb-3"><label class="form-label" for="bs-name">Your name *</label><input class="form-control" id="bs-name" type="text" name="name" autocomplete="name" required></div> <div class="mb-3"><label class="form-label" for="bs-email">Email *</label><input class="form-control" id="bs-email" type="email" name="email" autocomplete="email" required></div> <fieldset class="mb-3"><legend class="form-label mb-1">Will you be there? *</legend><div class="form-check"><input class="form-check-input" type="radio" name="attending" id="bs-attending-0" value="Yes, I will be there" required><label class="form-check-label" for="bs-attending-0">Yes, I will be there</label></div><div class="form-check"><input class="form-check-input" type="radio" name="attending" id="bs-attending-1" value="Sorry, I can't make it" required><label class="form-check-label" for="bs-attending-1">Sorry, I can't make it</label></div></fieldset> <div class="mb-3"><label class="form-label" for="bs-guests">How many people, including you?</label><input class="form-control" id="bs-guests" type="number" name="guests"></div> <div class="mb-3"><label class="form-label" for="bs-meal">Meal choice</label><select class="form-select" id="bs-meal" name="meal"><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="mb-3"><label class="form-label" for="bs-dietary">Allergies or dietary needs</label><textarea class="form-control" id="bs-dietary" name="dietary" rows="4"></textarea></div> <div class="mb-3"><label class="form-label" for="bs-note">A note for the hosts</label><textarea class="form-control" id="bs-note" name="note" rows="4"></textarea></div> <div class="position-absolute top-0 start-0 overflow-hidden" style="width:1px;height:1px" aria-hidden="true"><label>Leave this empty<input name="botcheck" tabindex="-1" autocomplete="off"></label></div> <button class="btn btn-primary" type="submit">Send RSVP</button> </form>
import { useEffect, useRef, useState } from "react";
// Visitor language for Formgong messages, thank-you text and autoreply.
const LANG = "en";
export default function ContactForm() {
const captcha = useRef(null);
const feedback = useRef(null);
const [failed, setFailed] = useState(false);
const [busy, setBusy] = useState(false);
const [status, setStatus] = useState("");
useEffect(() => mountCaptcha(captcha.current, null), []);
useEffect(() => { if (failed && status) feedback.current?.focus(); }, [failed, status]);
async function onSubmit(event) {
event.preventDefault();
if (busy) return;
const form = event.currentTarget;
const body = new FormData(form);
body.set("access_key", "fk_your_access_key");
body.set("_lang", LANG);
setBusy(true);
setFailed(false);
setStatus("Sending…");
try {
const response = await fetch("https://formgong.com/submit", {
method: "POST", headers: { Accept: "application/json" }, body,
});
const result = await response.json();
setFailed(!result.success);
setStatus(result.success ? (result.message || "Sent. Thank you!") : (result.message || "Could not send. Please try again."));
} catch { setFailed(true); setStatus("Connection failed. Please try again."); }
finally { setBusy(false); resetCaptcha(form); }
}
return <form id="fg-fk_your_access_key" onSubmit={onSubmit} aria-busy={busy}>
<style>{"#fg-fk_your_access_key{box-sizing:border-box;max-width:520px;width:100%;padding:28px;border:1px solid #dbe2ea;border-radius:8px;background:#fff;color:#0f172a;font:16px/1.5 system-ui,sans-serif;display:grid;gap:16px}#fg-fk_your_access_key *{box-sizing:border-box}#fg-fk_your_access_key h2{font-size:24px;line-height:1.3;margin:0 0 4px;color:#0f172a}#fg-fk_your_access_key label{display:grid;gap:6px;font-weight:500}#fg-fk_your_access_key input,#fg-fk_your_access_key textarea,#fg-fk_your_access_key select{width:100%;font:inherit;min-height:44px;border:1px solid #94a3b8;border-radius:8px;padding:10px 12px;background:#fff;color:#0f172a}#fg-fk_your_access_key textarea{min-height:96px;resize:vertical}#fg-fk_your_access_key .fg-reminder-consent{display:flex;align-items:flex-start;gap:10px;font-weight:400}#fg-fk_your_access_key input[type=checkbox]{width:20px;min-height:20px;flex-shrink:0;margin:2px 0}#fg-fk_your_access_key button{font:inherit;font-weight:600;min-height:48px;padding:12px 20px;border:0;border-radius:8px;background:#4338ca;color:#ffffff;cursor:pointer}#fg-fk_your_access_key :focus-visible{outline:3px solid #4338ca;outline-offset:3px}#fg-fk_your_access_key button:disabled{cursor:wait;opacity:.7}#fg-fk_your_access_key p{margin:0}#fg-fk_your_access_key fieldset{border:0;padding:0;margin:0;display:grid;gap:8px;min-width:0}#fg-fk_your_access_key legend{font-weight:500;padding:0;margin-bottom:6px}#fg-fk_your_access_key .fg-choice{display:flex;align-items:center;gap:10px;font-weight:400}#fg-fk_your_access_key input[type=radio]{width:20px;min-height:20px;flex-shrink:0;margin:0}#fg-fk_your_access_key .fg-trap{position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}"}</style>
<h2>{"RSVP"}</h2>
<label>{"Your name"} * <input type="text" name="name" required autoComplete="name" /></label>
<label>{"Email"} * <input type="email" name="email" required autoComplete="email" /></label>
<fieldset><legend>{"Will you be there?"} *</legend><label className="fg-choice"><input type="radio" name="attending" value={"Yes, I will be there"} required /> {"Yes, I will be there"}</label><label className="fg-choice"><input type="radio" name="attending" value={"Sorry, I can't make it"} required /> {"Sorry, I can't make it"}</label></fieldset>
<label>{"How many people, including you?"} <input type="number" name="guests" /></label>
<label>{"Meal choice"} <select name="meal"><option value="">—</option><option value={"Meat"}>{"Meat"}</option><option value={"Fish"}>{"Fish"}</option><option value={"Vegetarian"}>{"Vegetarian"}</option><option value={"Vegan"}>{"Vegan"}</option></select></label>
<label>{"Allergies or dietary needs"} <textarea name="dietary" /></label>
<label>{"A note for the hosts"} <textarea name="note" /></label>
<div aria-hidden="true" style={{position:"absolute",insetInlineStart:0,top:0,width:1,height:1,overflow:"hidden",clipPath:"inset(50%)"}}><input name="botcheck" tabIndex={-1} autoComplete="off" /></div>
<button type="submit" disabled={busy}>{busy ? "Sending…" : "Send RSVP"}</button>
<p ref={feedback} role="status" tabIndex={-1}>{status}</p>
</form>;
}
function mountCaptcha(node, siteKey) {
if (!node || !siteKey) return () => {};
let disposed = false;
let widget;
function render() {
if (disposed || !window.turnstile) return;
window.turnstile.ready(() => {
if (disposed) return;
widget = window.turnstile.render(node, { sitekey: siteKey, language: node.dataset.language || document.documentElement.lang || "auto" });
node.dataset.widgetId = widget;
});
}
if (window.turnstile) render();
else {
let script = document.querySelector('script[src^="https://challenges.cloudflare.com/turnstile/v0/api.js"]');
if (!script) {
script = document.createElement("script");
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
script.async = true;
document.head.appendChild(script);
}
script.addEventListener("load", render, { once: true });
}
return () => { disposed = true; if (widget !== undefined) window.turnstile?.remove(widget); };
}
function resetCaptcha(form) {
const widget = form.querySelector("[data-turnstile]")?.dataset.widgetId;
if (widget !== undefined) window.turnstile?.reset(widget);
}<script setup>
import { ref } from "vue";
const status = ref("");
const busy = ref(false);
async function onSubmit(event) {
const form = event.currentTarget;
if (busy.value || !form.reportValidity()) return;
const body = new FormData(form);
body.set("access_key", "fk_your_access_key");
body.set("_lang", "en");
busy.value = true;
status.value = "Sending…";
try {
const response = await fetch("https://formgong.com/submit", {
method: "POST",
headers: { Accept: "application/json" },
body,
});
const result = await response.json();
status.value = result.success ? (result.message || "Sent. Thank you!") : (result.message || "Could not send. Please try again.");
} catch {
status.value = "Connection failed. Please try again.";
} finally {
busy.value = false;
}
}
</script>
<template>
<form style="position:relative;display:grid;gap:16px;max-width:32rem" @submit.prevent="onSubmit" :aria-busy="busy">
<h2>RSVP</h2>
<label>Your name * <input type="text" name="name" required autocomplete="name"></label>
<label>Email * <input type="email" name="email" required autocomplete="email"></label>
<fieldset><legend>Will you be there? *</legend><label class="fg-choice"><input type="radio" name="attending" value="Yes, I will be there" required> Yes, I will be there</label><label class="fg-choice"><input type="radio" name="attending" value="Sorry, I can't make it" required> Sorry, I can't make it</label></fieldset>
<label>How many people, including you? <input type="number" name="guests"></label>
<label>Meal choice <select name="meal"><option value="">—</option><option value="Meat">Meat</option><option value="Fish">Fish</option><option value="Vegetarian">Vegetarian</option><option value="Vegan">Vegan</option></select></label>
<label>Allergies or dietary needs <textarea name="dietary"></textarea></label>
<label>A note for the hosts <textarea name="note"></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)"><input name="botcheck" tabindex="-1" autocomplete="off"></div>
<button type="submit" :disabled="busy">Send RSVP</button>
<p role="status" tabindex="-1">{{ status }}</p>
</form>
</template>Create a free form, then open Connect on that form in this browser. If it still has the default name, email and message fields, they are replaced with this form.
| Field | Type | Required |
|---|---|---|
| Your name, email | Text, email | Yes |
| Will you be there? | Radio: yes or no, in words | Yes |
| How many people, including you? | Number | No |
| Meal choice, allergies, a note | Select, two textareas | No |
What an RSVP form should ask
- Yes or no first. Two radio buttons with the answer in words: “Yes, I will be there” and “Sorry, I can’t make it”. A bare Yes or No is easy to misread when you scan a list of replies.
- How many people. A number field that includes the person replying. Say “including you” in the label, or you will get both kinds of answer.
- Meal choice. Optional in the sample, because people who are not coming should not have to choose a dinner.
- Allergies. A free text field. The caterer needs “no nuts, severe” more than a tick in a box.
- A note. Optional. This is where the congratulations go.
If each guest needs their own meal, ask for names and meals in the note, or put one meal question per guest. For events with ticket types, the registration form generator is the closer match.
Turning replies into a guest list
Connect Google Sheets and every RSVP becomes a row: name, attending, guests, meal. Filter by “Yes” and add up the guests column for your head count. Share the sheet with whoever plans the seating.
This form does not stop at a number of seats or on a date. When the RSVP deadline passes, pause the form in its Formgong settings, or take it off the page. To send people to your own thank-you page, with the date and the address again, add a hidden _redirect field that points to it.
Free limits, email and storage
The RSVP form code is free to copy. Replies are delivered only after you replace the placeholder key.
Copying the code needs no account. AI generations are limited to 5 an hour and 10 a day for each network, plus 100 a day for the whole site. When a limit is hit, use “Build it yourself, without AI”. That path does not call the model.
On the free plan, Telegram is instant and email is sent for every submission. The free plan is 1,000 submissions a month. Auto-reply is not on the free plan. Submission data is stored in the EU. Support is Formgong at support@formgong.com.
Your description is sent to the model so it can choose fields. It is not stored. Do not paste passwords, card numbers or other secrets.
Questions
What is an RSVP form?
The reply form for an invitation. Guests say whether they are coming, how many people they bring, and anything the hosts need to know, such as meal choice or allergies.
How do I make an RSVP form for a wedding website?
Copy the HTML tab on this page, replace fk_your_access_key with a free Formgong key and paste it into the wedding site. Send one test reply before you share the link.
Can I get the RSVPs in a spreadsheet?
Yes. Connect Google Sheets and each reply becomes a row you can filter and count.
Does the form close after the RSVP date?
Not by itself. Pause the form in Formgong when the date passes, or remove it from the page.
Does it work without a website builder?
Yes. The HTML is a normal form. Save it as rsvp.html on any host, including GitHub Pages.
Sources
Checked on 16.10.2026 against these public pages: MDN: input type=number, MDN: input type=radio, Formgong HTML guide.