Skip to content

Registration forms · 5 fields

RSVP form template

For invited guests rather than the public: a party, a wedding, a team dinner, an opening. Guests say whether they are coming and how many they bring, and you get a head count you can plan with.

Get the code

RSVP

Live demo: try the fields. Submitting sends nothing.

Optional. Only what the kitchen needs to know.

Why these fields

  • Name

    text · required

    Required, to match the answer to the guest list.

  • Email

    email · required

    Required, for changes and reminders.

  • Will you join us?

    radio · required

    Required. Not sure yet beats no answer: you know whom to remind.

  • Number of guests, including you

    number · optional

    Optional. The generated input is a plain number, so add min="1" and a max that matches your invitation, and the browser refuses impossible counts.

  • Dietary requirements

    textarea · optional

    Optional, and the most sensitive field here: allergies are health data and some diets reveal religion. Ask only what the kitchen needs and delete the answers after the event.

When to use it

Use it when you know who is invited. For open events with ticket types and a capacity, the event registration template fits better.

No website for the event? The hosted RSVP template gives you a page to link from the invitation.

Privacy and GDPR

  • Guests share these details to attend, so no consent box is needed to organise the event. Do not reuse the list for anything else afterwards.
  • Dietary answers can be special category data under Article 9. Keep them out of widely shared spreadsheets and set a short retention, such as 30 days after the event.

Choose your stack. Copy your form.

Replace the example endpoint with your Formward endpoint, then adapt the fields to your needs.

<form action="https://forms.formward.eu/f/your-form-id" method="POST">
  <label for="name">Name</label>
  <input type="text" name="name" id="name" required />
  <label for="email">Email</label>
  <input type="email" name="email" id="email" required />
  <label for="attending">Will you join us?</label>
  <div role="radiogroup">
    <label for="attending-0">
      <input type="radio" name="attending" id="attending-0" value="Yes" required /> Yes
    </label>
    <label for="attending-1">
      <input type="radio" name="attending" id="attending-1" value="No" /> No
    </label>
    <label for="attending-2">
      <input type="radio" name="attending" id="attending-2" value="Not sure yet" /> Not sure yet
    </label>
  </div>
  <label for="guests">Number of guests, including you</label>
  <input type="number" name="guests" id="guests" />
  <label for="dietary">Dietary requirements</label>
  <small id="dietary-help">Optional. Only what the kitchen needs to know.</small>
  <textarea name="dietary" id="dietary" aria-describedby="dietary-help"></textarea>
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px" aria-hidden="true" />
  <button type="submit">Send</button>
</form>

Accessible by default, and how to keep it that way

  • Every field in the code has a visible label tied to it with for and id, so screen readers announce what to enter and a click on the label focuses the field.
  • Required fields carry the required attribute, so the browser explains a missing answer before anything is sent. Say “required” in words as well; an asterisk or a colour alone is easy to miss.
  • The spam trap field (_gotcha) is hidden from screen readers with aria-hidden and skipped by the Tab key, so people never meet it.
  • In the JavaScript versions, show the confirmation or error in an element with role="status" so the result is announced, and keep the entered answers when sending fails.

Changed the fields? Paste your version into the HTML form tester to see exactly what it sends, or run it through the GDPR form checker.

How the code talks to Formward

Each form you create gets its own endpoint in the form https://forms.formward.eu/f/your-form-id. The HTML version posts to it directly and the browser is redirected to a thank-you page, so it works without JavaScript.

The Next.js version below sends the same fields with fetch and an Accept: application/json header. Formward then answers with { ok: true, id }, or an error body with 402 when the plan limit is reached and 429 when the rate limit kicks in. See responses and status codes.

Next.js client component

"use client";

import { useState } from "react";

export function RsvpForm() {
  const [sent, setSent] = useState(false);

  async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const form = e.currentTarget;
    const res = await fetch("https://forms.formward.eu/f/your-form-id", {
      method: "POST",
      headers: { Accept: "application/json" },
      body: new FormData(form),
    });
    if (res.ok) {
      setSent(true);
      form.reset();
    }
  }

  if (sent) return <p>Thanks! Your message has been sent.</p>;

  return (
    <form onSubmit={onSubmit}>
      <label htmlFor="name">Name</label>
      <input type="text" name="name" id="name" required />
      <label htmlFor="email">Email</label>
      <input type="email" name="email" id="email" required />
      <label htmlFor="attending">Will you join us?</label>
      <div role="radiogroup">
        <label htmlFor="attending-0">
          <input type="radio" name="attending" id="attending-0" value="Yes" required /> Yes
        </label>
        <label htmlFor="attending-1">
          <input type="radio" name="attending" id="attending-1" value="No" /> No
        </label>
        <label htmlFor="attending-2">
          <input type="radio" name="attending" id="attending-2" value="Not sure yet" /> Not sure yet
        </label>
      </div>
      <label htmlFor="guests">Number of guests, including you</label>
      <input type="number" name="guests" id="guests" />
      <label htmlFor="dietary">Dietary requirements</label>
      <small id="dietary-help">Optional. Only what the kitchen needs to know.</small>
      <textarea name="dietary" id="dietary" aria-describedby="dietary-help" />
      <input
        type="text"
        name="_gotcha"
        tabIndex={-1}
        autoComplete="off"
        style={{ position: "absolute", left: "-9999px" }}
        aria-hidden="true"
      />
      <button type="submit">Send</button>
    </form>
  );
}

Spam protection

  • The generated code already includes the hidden _gotcha honeypot. Leave it in: a bot that fills it gets a normal success response, the submission is filed as spam and no email is sent.
  • Every form has a per-IP rate limit, and you can restrict it to your own domains with the allowed-origins list in the form settings.
  • Cloudflare Turnstile is optional and works on every plan, including Free. Turn it on in the form settings, add the widget to your markup and Formward checks the token server-side.
  • The form settings can also reject disposable email addresses, which is worth turning on when a fake address would waste your time.

What happens after submit

  • Each answer is emailed to you and stored in the EU on every plan. Export the guest list as CSV from Personal up.
  • From Professional, the autoresponder can send guests the date, the address and what to bring.
  • Set a closing date in the form's response settings to match your reply-by date.

Questions

How do I set a reply-by date?
Set a closing date in the form's response settings. After it passes, the form stops accepting answers and shows your closed message.
How is this different from the event registration template?
RSVP is for invited guests and asks whether they are coming. Event registration is for open sign-ups and asks which ticket they want.

Customize before publishing

  • Remove fields you do not need and mark only essential answers as required.
  • Replace placeholder wording with terms your audience already understands.
  • Add your privacy notice, retention details and expected response time.
  • Test keyboard focus, validation errors and the confirmation state on mobile.

Use this template

Create a free account and the form is set up from this template. Copy your endpoint and replace https://forms.formward.eu/f/your-form-id in the code above.

Use this template →

No website? Use a hosted form