Doku /
Formulare
Jedes HTML-Formular auf einer Lobsite-Website kann Nachrichten sammeln: Lass seine action auf /_lobsite/forms/<name> zeigen und deploye. Es gibt kein Backend zu schreiben, kein Skript einzubinden und keinen Schlüssel einzufügen. Einsendungen landen auf der Seite „Einsendungen“ in deinem Dashboard und in deinem Postfach.
<form action="/_lobsite/forms/contact" method="POST">
<input name="email" type="email" required>
<textarea name="message" required></textarea>
<button>Send</button>
</form>
Wie Formulare funktionieren
- Die Action benennt das Formular.
/_lobsite/forms/contactist das Formularcontact. Namen bestehen aus Kleinbuchstaben, Ziffern,-und_. Nutze einen Namen pro Zweck (contact,newsletter,quote); mehrere Seiten können sich ein Formular teilen. - Formulare werden beim Deploy erkannt. Das Deploy liest die HTML-Dateien und erfasst jedes Formular, das an
/_lobsite/forms/sendet. Das Formular muss in einer HTML-Datei im deployten Ordner stehen: Ein Formular, das erst entsteht, wenn JavaScript es rendert, wird nicht gefunden (siehe Frameworks). - Felder werden unter ihrem Namen gespeichert. Jedes Feld mit einem
namewird als Text aufbewahrt. Ein Feld namensemailwird als Reply-To der Benachrichtigungs-E-Mail und als Titel auf der Seite „Einsendungen“ verwendet. Datei-Uploads werden nicht unterstützt. - Spamschutz wird für dich hinzugefügt. Wenn die Seite ausgeliefert wird, bekommt das Formular ein verstecktes Honeypot-Feld und einen signierten Zeitstempel. Einsendungen, die den Honeypot ausfüllen oder innerhalb von 2 Sekunden zurückkommen, werden als Spam abgesondert, und zu viele hintereinander von einem Besucher werden abgewiesen.
- Nach dem Senden sieht der Besucher eine Dankesseite mit einem Link zurück oder die Seite, die du mit
redirectfestgelegt hast. - Formulare funktionieren unter Produktions-URLs. Vorschau-Deploys nehmen keine Einsendungen an, und eine ohne Konto deployte Website nimmt sie an, sobald sie übernommen ist.
Formulartypen
Jedes Formular ist ein Kontaktformular oder eine Warteliste. Der Typ bestimmt, wie seine Einsendungen auf der Seite „Einsendungen“ angezeigt werden: Die Zeilen eines Kontaktformulars zeigen die Nachricht, die Zeilen einer Warteliste zeigen, wer sich eingetragen hat und von welcher Seite, und Wartelisten werden über der Tabelle gezählt. Beide senden dieselbe Benachrichtigungs-E-Mail.
Lobsite wählt den Typ beim Deploy:
- Ein Formular, in das Besucher eine E-Mail und höchstens einen Namen eintragen, ist eine Warteliste. Versteckte Felder, Felder, die mit
_beginnen, und Checkboxen (ein Einwilligungshäkchen) zählen nicht. - Ebenso ein Formular namens
waitlist,newsletter,signup,subscribe,early-access,betaodernotify, egal welche Felder es hat. - Jedes andere Formular ist ein Kontaktformular.
Um selbst zu wählen, setz type in lobsite.toml:
[forms.launch]
type = "waitlist" # or "contact"
Anmeldungen zu Wartelisten werden aufbewahrt, solange das Formular existiert; andere Einsendungen für die Aufbewahrungsdauer des Tarifs (siehe Limits).
Kontaktformular
Eine vollständige Seite mit Name, E-Mail und Nachricht. Die Labels und die autocomplete-Werte machen das Ausfüllen leicht; die required-Attribute stoppen eine leere Einsendung, bevor sie abgeschickt wird.
<!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>
Um dieselben Felder auf dem Server zu prüfen und Besucher auf deine eigene Dankesseite zu schicken, füg das Formular zu lobsite.toml hinzu und erstelle thanks.html:
[forms.contact]
required = ["name", "email", "message"]
types = { email = "email" }
redirect = "/thanks"
Warteliste
Vor dem Start brauchst du nur ein E-Mail-Feld. Der Name des Formulars macht es zur Warteliste; type sagt es ausdrücklich. Anmeldungen werden auf der Seite „Einsendungen“ gezählt und aufbewahrt, solange das Formular existiert.
<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" }
Newsletter-Anmeldung
Ein Feld reicht. Ein zweites Formular auf derselben Website bekommt einen eigenen Namen, damit Anmeldungen und Nachrichten auf der Seite „Einsendungen“ und in Exporten getrennt bleiben. Ein Formular mit nur einem E-Mail-Feld (und höchstens einem Namen) ist eine Warteliste: siehe Formulartypen.
<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 ist ein verstecktes Feld, das die nach dem Senden angezeigte Seite wählt. Es muss ein Pfad oder eine URL auf derselben Website sein; redirect in lobsite.toml hat Vorrang.
Angebotsanfrage
Auswahllisten, Optionsfelder und Checkboxen funktionieren wie gewohnt. Checkboxen mit demselben Namen werden als ein kommagetrennter Wert gespeichert.
<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>
Senden, ohne die Seite zu verlassen
Um statt einer neuen Seite eine Meldung an Ort und Stelle zu zeigen, sende das Formular mit fetch. Bau den Body mit new FormData(form), damit die versteckten Spam-Felder mitgehen, und fordere mit dem Accept-Header JSON an:
<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>
Die Antwort ist {"ok": true}, oder {"ok": false, "errors": {"email": "Required"}} für Felder, die nicht bestanden haben, oder {"ok": false, "error": "rate_limited"} (auch too_large, not_found, forms_off). Ohne das Skript funktioniert dasselbe Formular weiterhin als schlichtes Formular.
Frameworks
React, Vue, Svelte, Astro und die anderen funktionieren, wenn das Formular im gebauten HTML steht, wie es Prerendering und statischer Export erzeugen (Astro und Eleventy standardmäßig, Next.js mit output: "export", SvelteKit mit prerender, Nuxt mit nuxt generate). Lass die Attribute action und method direkt am <form>-Element.
In einer Single-Page-App muss das Formular im gebauten HTML stehen und so bleiben, wie es ausgeliefert wurde: Ein Formular, das nur in JavaScript existiert, wird nicht erfasst und seine Einsendungen werden abgewiesen, und ein Formular, das der Browser neu rendert, verliert die Spam-Felder, sodass seine Nachrichten im Spam landen.
// 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>
);
}
Einstellungen
Jedes Formular kann einen Abschnitt in lobsite.toml haben. Alle Schlüssel sind optional; die Einstellungen gehen mit dem Deploy mit.
[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
Eine Einsendung, die an required oder types scheitert, wird nicht gespeichert; der Besucher sieht, was er korrigieren muss, und einen Link zurück. Im kostenlosen Tarif kann notify nur die E-Mail deines Kontos sein, und webhook ist nicht verfügbar.
Einsendungen lesen
- Die Seite „Einsendungen“ in deinem Dashboard zeigt die Einsendungen aller Formulare in einer Tabelle. Durchsuche sie, grenze sie nach Website und Formulartyp ein und wechsle zu Spam, um zu sehen, was die Prüfungen abgefangen haben. Eine Einsendung ist neu, bis du sie öffnest.
- Jede Nachricht wird an die Adresse deines Kontos gemailt, mit Reply-To auf den Absender.
lobsite forms lslistet deine Formulare auf;lobsite forms export contact --csvlädt die Einsendungen eines Formulars herunter. „Als CSV exportieren“ auf der Seite „Einsendungen“ lädt herunter, was die Tabelle zeigt.
Im kostenlosen Tarif laufen Formulare im eingeschränkten Modus: ein monatliches Kontingent pro Website, Benachrichtigungen nur an die E-Mail deines Kontos und keine Webhooks. Der Standard-Tarif bringt Webhooks, jede bestätigte Benachrichtigungsadresse und keine monatliche Obergrenze. Siehe Limits.