lobsite! Inloggen Registreren

Docs /

Formulieren

Elk HTML-formulier op een Lobsite-site kan berichten verzamelen: laat de action wijzen naar /_lobsite/forms/<name> en deploy. Er is geen backend om te schrijven, geen script om toe te voegen en geen sleutel om te plakken. Inzendingen komen binnen op de pagina Inzendingen in je dashboard en in je e-mail.

<form action="/_lobsite/forms/contact" method="POST">
  <input name="email" type="email" required>
  <textarea name="message" required></textarea>
  <button>Send</button>
</form>

Hoe formulieren werken

  • De action geeft het formulier een naam. /_lobsite/forms/contact is het formulier contact. Namen bestaan uit kleine letters, cijfers, - en _. Gebruik één naam per doel (contact, newsletter, quote); meerdere pagina's kunnen één formulier delen.
  • Formulieren worden bij de deploy gevonden. De deploy leest de HTML-bestanden en registreert elk formulier dat naar /_lobsite/forms/ post. Het formulier moet in een HTML-bestand in de gedeployde map staan: een formulier dat pas bestaat als JavaScript het rendert, wordt niet gevonden (zie Frameworks).
  • Velden worden opgeslagen onder de naam die je ze geeft. Elk veld met een name wordt bewaard, als tekst. Een veld met de naam email wordt gebruikt als Reply-To van de meldingsmail en als titel op de pagina Inzendingen. Bestandsuploads worden niet ondersteund.
  • Spambescherming wordt voor je toegevoegd. Als de pagina wordt geserveerd, krijgt het formulier een verborgen honeypotveld en een ondertekende tijdstempel. Inzendingen die de honeypot invullen of binnen 2 seconden terugkomen, worden apart gezet als spam, en te veel achter elkaar van één bezoeker worden geweigerd.
  • Na het verzenden ziet de bezoeker een bedankpagina met een link terug, of de pagina die je met redirect instelt.
  • Formulieren werken op productie-URL's. Voorbeelddeploys accepteren geen inzendingen, en een site die zonder account is gedeployd, accepteert ze zodra hij is geclaimd.

Soorten formulieren

Elk formulier is een contactformulier of een wachtlijst. Het type bepaalt hoe de inzendingen op de pagina Inzendingen worden getoond: de rijen van een contactformulier tonen het bericht, die van een wachtlijst tonen wie zich aanmeldde en vanaf welke pagina, en wachtlijsten worden boven de tabel geteld. Beide sturen dezelfde meldingsmail.

Lobsite kiest het type bij de deploy:

  • Een formulier waarin bezoekers een e-mailadres en hooguit een naam invullen, is een wachtlijst. Verborgen velden, velden die met _ beginnen en selectievakjes (een toestemmingsvakje) tellen niet mee.
  • Dat geldt ook voor een formulier met de naam waitlist, newsletter, signup, subscribe, early-access, beta of notify, welke velden het ook heeft.
  • Elk ander formulier is een contactformulier.

Wil je zelf kiezen, stel dan type in lobsite.toml in:

[forms.launch]
type = "waitlist"   # or "contact"

Aanmeldingen voor een wachtlijst blijven bewaard zolang het formulier bestaat; andere inzendingen gedurende de bewaartermijn van het abonnement (zie Limieten).

Contactformulier

Een complete pagina met naam, e-mailadres en bericht. De labels en de autocomplete-waarden maken het invullen makkelijk; de required-attributen houden een lege inzending tegen voor hij wordt verstuurd.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Contact</title>
</head>
<body>
  <h1>Get in touch</h1>
  <form action="/_lobsite/forms/contact" method="POST">
    <label>Name
      <input name="name" autocomplete="name" required>
    </label>
    <label>Email
      <input name="email" type="email" autocomplete="email" required>
    </label>
    <label>Message
      <textarea name="message" rows="5" required></textarea>
    </label>
    <button type="submit">Send</button>
  </form>
</body>
</html>

Wil je dezelfde velden op de server controleren en bezoekers naar je eigen bedankpagina sturen, voeg het formulier dan toe aan lobsite.toml en maak thanks.html:

[forms.contact]
required = ["name", "email", "message"]
types    = { email = "email" }
redirect = "/thanks"

Wachtlijst

Voor de lancering heb je alleen een e-mailveld nodig. De naam van het formulier maakt het een wachtlijst; type instellen zegt het expliciet. Aanmeldingen worden geteld op de pagina Inzendingen en bewaard zolang het formulier bestaat.

<form action="/_lobsite/forms/waitlist" method="POST">
  <label for="wl-email">Get early access</label>
  <input id="wl-email" name="email" type="email" autocomplete="email" placeholder="you@example.com" required>
  <button>Join the waitlist</button>
</form>
[forms.waitlist]
type     = "waitlist"
required = ["email"]
types    = { email = "email" }

Aanmelden voor een nieuwsbrief

Eén veld is genoeg. Een tweede formulier op dezelfde site krijgt een eigen naam, zodat aanmeldingen en berichten gescheiden blijven op de pagina Inzendingen en in exports. Een formulier met alleen een e-mailveld (en hooguit een naam) is een wachtlijst: zie Soorten formulieren.

<form action="/_lobsite/forms/newsletter" method="POST">
  <label for="nl-email">Get updates by email</label>
  <input id="nl-email" name="email" type="email" autocomplete="email" required>
  <input type="hidden" name="_redirect" value="/subscribed">
  <button>Subscribe</button>
</form>

_redirect is een verborgen veld dat de pagina kiest die na het verzenden wordt getoond. Het moet een pad of een URL op dezelfde site zijn; redirect in lobsite.toml gaat voor.

Offerteaanvraag

Keuzelijsten, keuzerondjes en selectievakjes werken zoals gewoonlijk. Selectievakjes met dezelfde naam worden opgeslagen als één waarde, gescheiden door komma's.

<form action="/_lobsite/forms/quote" method="POST">
  <input name="name" autocomplete="name" required>
  <input name="email" type="email" autocomplete="email" required>
  <input name="phone" type="tel" autocomplete="tel">
  <select name="budget">
    <option>Under $1,000</option>
    <option>$1,000 to $5,000</option>
    <option>Over $5,000</option>
  </select>
  <fieldset>
    <legend>Services</legend>
    <label><input type="checkbox" name="services" value="Design"> Design</label>
    <label><input type="checkbox" name="services" value="Development"> Development</label>
    <label><input type="checkbox" name="services" value="Hosting"> Hosting</label>
  </fieldset>
  <textarea name="details" required></textarea>
  <button>Request a quote</button>
</form>

Verzenden zonder de pagina te verlaten

Wil je een melding op de pagina tonen in plaats van een nieuwe pagina te laden, verstuur het formulier dan met fetch. Bouw de body met new FormData(form) zodat de verborgen spamvelden meegaan, en vraag om JSON met de Accept-header:

<form id="contact" action="/_lobsite/forms/contact" method="POST">
  <input name="email" type="email" required>
  <textarea name="message" required></textarea>
  <button>Send</button>
  <p id="contact-status" role="status"></p>
</form>
<script>
  const form = document.getElementById("contact");
  const status = document.getElementById("contact-status");
  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    status.textContent = "Sending…";
    const res = await fetch(form.action, {
      method: "POST",
      body: new FormData(form),
      headers: { Accept: "application/json" },
    });
    const answer = await res.json();
    if (answer.ok) {
      form.reset();
      status.textContent = "Thanks! We'll be in touch.";
    } else {
      status.textContent = answer.errors ? Object.entries(answer.errors).map(([field, why]) => `${field}: ${why}`).join(", ") : "Something went wrong. Please try again.";
    }
  });
</script>

Het antwoord is {"ok": true}, of {"ok": false, "errors": {"email": "Required"}} voor velden die niet door de controle kwamen, of {"ok": false, "error": "rate_limited"} (ook too_large, not_found, forms_off). Zonder het script werkt hetzelfde formulier nog steeds als gewoon formulier.

Frameworks

React, Vue, Svelte, Astro en de rest werken als het formulier in de gebouwde HTML staat, wat prerendering en statische export opleveren (Astro en Eleventy standaard, Next.js met output: "export", SvelteKit met prerender, Nuxt met nuxt generate). Houd de attributen action en method op het <form>-element zelf.

In een single-page-app moet het formulier in de gebouwde HTML staan en blijven zoals het is geserveerd: een formulier dat alleen in JavaScript bestaat, wordt niet geregistreerd en de inzendingen worden geweigerd, en een formulier dat de browser opnieuw rendert, verliest de spamvelden, waardoor de berichten in de spam belanden.

// React: a plain form element, prerendered into the HTML.
export function Contact() {
  return (
    <form action="/_lobsite/forms/contact" method="POST">
      <input name="email" type="email" required />
      <textarea name="message" required />
      <button>Send</button>
    </form>
  );
}

Instellingen

Elk formulier kan een sectie in lobsite.toml hebben. Alle sleutels zijn optioneel; de instellingen gaan met de deploy mee.

[forms.contact]
type      = "contact"                            # contact or waitlist; inferred when left out
required  = ["email", "message"]                 # fields that can't be empty
types     = { email = "email", phone = "tel" }   # text, email, number, url or tel
redirect  = "/thanks"                            # the page shown after sending
notify    = ["you@example.com"]                  # who gets an email for each message
webhook   = "https://example.com/hooks/contact"  # POSTs each submission as JSON

Een inzending die niet voldoet aan required of types, wordt niet opgeslagen; de bezoeker ziet wat hij moet verbeteren en een link terug. Op het gratis abonnement kan notify alleen het e-mailadres van je account zijn, en webhook is niet beschikbaar.

Inzendingen lezen

  • De pagina Inzendingen in je dashboard toont de inzendingen van alle formulieren in één tabel. Doorzoek ze, filter ze op site en op soort formulier, en schakel naar spam om te zien wat de controles hebben tegengehouden. Een inzending is nieuw tot je hem opent.
  • Elk bericht wordt gemaild naar het adres van je account, met Reply-To ingesteld op de afzender.
  • lobsite forms ls toont je formulieren; lobsite forms export contact --csv downloadt de inzendingen van één formulier. Exporteren als CSV op de pagina Inzendingen downloadt wat de tabel toont.

Op het gratis abonnement draaien formulieren in beperkte modus: een maandelijks quotum per site, meldingen alleen naar het e-mailadres van je account, en geen webhooks. Het Standard-abonnement voegt webhooks toe, elk geverifieerd meldingsadres en geen maandlimiet. Zie Limieten.