lobsite! Zaloguj się Załóż konto

Dokumentacja /

Formularze

Każdy formularz HTML na stronie w Lobsite może zbierać wiadomości: skieruj jego action na /_lobsite/forms/<name> i wdróż. Nie trzeba pisać backendu, dodawać skryptu ani wklejać klucza. Zgłoszenia trafiają na stronę „Zgłoszenia” w Twoim panelu i na Twój e-mail.

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

Jak działają formularze

  • Action nadaje formularzowi nazwę. /_lobsite/forms/contact to formularz contact. Nazwy składają się z małych liter, cyfr, - i _. Używaj jednej nazwy na jeden cel (contact, newsletter, quote); kilka stron może współdzielić jeden formularz.
  • Formularze są wykrywane podczas wdrożenia. Wdrożenie czyta pliki HTML i zapisuje każdy formularz wysyłający do /_lobsite/forms/. Formularz musi być w pliku HTML we wdrażanym folderze: formularz, który powstaje dopiero po wyrenderowaniu przez JavaScript, nie zostanie znaleziony (zobacz Frameworki).
  • Pola są zapisywane pod nadanymi nazwami. Każde pole z atrybutem name jest zachowywane jako tekst. Pole o nazwie email służy jako Reply-To w e-mailu z powiadomieniem i jako tytuł na stronie „Zgłoszenia”. Przesyłanie plików nie jest obsługiwane.
  • Ochrona przed spamem jest dodawana za Ciebie. Przy serwowaniu strony do formularza dodawane jest ukryte pole-pułapka i podpisany znacznik czasu. Zgłoszenia, które wypełniają pułapkę lub wracają w ciągu 2 sekund, są odkładane jako spam, a zbyt wiele pod rząd od jednego odwiedzającego jest odrzucanych.
  • Po wysłaniu odwiedzający widzi stronę z podziękowaniem i linkiem powrotnym albo stronę ustawioną przez redirect.
  • Formularze działają pod produkcyjnymi adresami URL. Wdrożenia podglądowe nie przyjmują zgłoszeń, a strona wdrożona bez konta przyjmuje je po przejęciu.

Typy formularzy

Każdy formularz jest formularzem kontaktowym albo listą oczekujących. Typ decyduje, jak jego zgłoszenia są pokazywane na stronie „Zgłoszenia”: wiersze formularza kontaktowego pokazują wiadomość, wiersze listy oczekujących pokazują, kto się zapisał i z której strony, a listy oczekujących są liczone nad tabelą. Oba wysyłają ten sam e-mail z powiadomieniem.

Lobsite wybiera typ podczas wdrożenia:

  • Formularz, w którym odwiedzający podają e-mail i co najwyżej imię, jest listą oczekujących. Pola ukryte, pola zaczynające się od _ i pola wyboru (zgoda) się nie liczą.
  • Tak samo formularz o nazwie waitlist, newsletter, signup, subscribe, early-access, beta lub notify, niezależnie od pól.
  • Każdy inny formularz jest formularzem kontaktowym.

Aby wybrać samodzielnie, ustaw type w lobsite.toml:

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

Zapisy na listę oczekujących są przechowywane, dopóki formularz istnieje; inne zgłoszenia przez okres przechowywania z planu (zobacz Limity).

Formularz kontaktowy

Kompletna strona z imieniem, e-mailem i wiadomością. Etykiety i wartości autocomplete ułatwiają wypełnianie; atrybuty required zatrzymują puste zgłoszenie przed wysłaniem.

<!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>

Aby sprawdzać te same pola na serwerze i kierować odwiedzających na własną stronę z podziękowaniem, dodaj formularz do lobsite.toml i utwórz thanks.html:

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

Lista oczekujących

Przed premierą wystarczy pole e-mail. Nazwa formularza czyni go listą oczekujących; ustawienie type mówi to wprost. Zapisy są liczone na stronie „Zgłoszenia” i przechowywane, dopóki formularz istnieje.

<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" }

Zapis do newslettera

Wystarczy jedno pole. Drugi formularz na tej samej stronie dostaje własną nazwę, więc zapisy i wiadomości są rozdzielone na stronie „Zgłoszenia” i w eksportach. Formularz z samym polem e-mail (i co najwyżej imieniem) jest listą oczekujących: zobacz Typy formularzy.

<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 to ukryte pole, które wybiera stronę pokazywaną po wysłaniu. Musi to być ścieżka lub URL na tej samej stronie; redirect w lobsite.toml ma pierwszeństwo.

Zapytanie ofertowe

Listy rozwijane, przyciski opcji i pola wyboru działają jak zwykle. Pola wyboru o tej samej nazwie są zapisywane jako jedna wartość rozdzielona przecinkami.

<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>

Wysyłanie bez opuszczania strony

Aby pokazać komunikat na miejscu zamiast ładować nową stronę, wyślij formularz przez fetch. Zbuduj treść przez new FormData(form), aby ukryte pola antyspamowe poszły razem z nią, i poproś o JSON nagłówkiem Accept:

<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>

Odpowiedź to {"ok": true} albo {"ok": false, "errors": {"email": "Required"}} dla pól, które nie przeszły, albo {"ok": false, "error": "rate_limited"} (także too_large, not_found, forms_off). Bez skryptu ten sam formularz nadal działa jako zwykły formularz.

Frameworki

React, Vue, Svelte, Astro i inne działają, gdy formularz jest w zbudowanym HTML, co dają prerendering i eksport statyczny (Astro i Eleventy domyślnie, Next.js z output: "export", SvelteKit z prerender, Nuxt z nuxt generate). Trzymaj atrybuty action i method bezpośrednio na elemencie <form>.

W aplikacji jednostronicowej formularz musi być w zbudowanym HTML i pozostać taki, jak został podany: formularz istniejący tylko w JavaScripcie nie jest zapisywany, a jego zgłoszenia są odrzucane, a formularz renderowany na nowo przez przeglądarkę traci pola antyspamowe, więc jego wiadomości trafiają do spamu.

// 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>
  );
}

Ustawienia

Każdy formularz może mieć sekcję w lobsite.toml. Wszystkie klucze są opcjonalne; ustawienia jadą razem z wdrożeniem.

[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

Zgłoszenie, które nie przejdzie required lub types, nie jest zapisywane; odwiedzający widzi, co poprawić, i link powrotny. W darmowym planie notify może być tylko e-mailem Twojego konta, a webhook jest niedostępny.

Czytanie zgłoszeń

  • Strona „Zgłoszenia” w panelu pokazuje zgłoszenia ze wszystkich formularzy w jednej tabeli. Przeszukuj je, zawężaj według strony i typu formularza i przełącz się na spam, aby zobaczyć, co wyłapały kontrole. Zgłoszenie jest nowe, dopóki go nie otworzysz.
  • Każda wiadomość jest wysyłana e-mailem na adres Twojego konta, z Reply-To ustawionym na nadawcę.
  • lobsite forms ls wyświetla Twoje formularze; lobsite forms export contact --csv pobiera zgłoszenia z jednego formularza. Eksport CSV na stronie „Zgłoszenia” pobiera to, co pokazuje tabela.

W darmowym planie formularze działają w trybie ograniczonym: miesięczny limit na stronę, powiadomienia tylko na e-mail konta i bez webhooków. Plan Standard dodaje webhooki, dowolny zweryfikowany adres powiadomień i brak miesięcznego limitu. Zobacz Limity.