lobsite! Se connecter S'inscrire

Docs /

Formulaires

N’importe quel formulaire HTML d’un site Lobsite peut recueillir des messages : faites pointer son action vers /_lobsite/forms/<name> et déployez. Pas de backend à écrire, pas de script à ajouter, pas de clé à coller. Les réponses arrivent sur la page Envois de votre tableau de bord et par e-mail.

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

Comment fonctionnent les formulaires

  • L’action donne son nom au formulaire. /_lobsite/forms/contact est le formulaire contact. Les noms se composent de lettres minuscules, de chiffres, de - et de _. Utilisez un nom par usage (contact, newsletter, quote) ; plusieurs pages peuvent partager un formulaire.
  • Les formulaires sont détectés au déploiement. Le déploiement lit les fichiers HTML et enregistre chaque formulaire qui envoie vers /_lobsite/forms/. Le formulaire doit se trouver dans un fichier HTML du dossier déployé : un formulaire qui n’existe qu’une fois rendu par JavaScript n’est pas détecté (voir Frameworks).
  • Les champs sont enregistrés sous leur nom. Chaque champ qui a un name est conservé, sous forme de texte. Un champ nommé email sert de Reply-To à l’e-mail de notification et de titre sur la page Envois. L’envoi de fichiers n’est pas pris en charge.
  • La protection anti-spam est ajoutée pour vous. Quand la page est servie, un champ piège caché et un horodatage signé sont ajoutés au formulaire. Les réponses qui remplissent le piège ou reviennent en moins de 2 secondes sont mises de côté comme spam, et un visiteur qui en envoie trop à la suite est refusé.
  • Après l’envoi, le visiteur voit une page de remerciement avec un lien de retour, ou la page définie avec redirect.
  • Les formulaires fonctionnent sur les URL de production. Les déploiements d’aperçu n’acceptent pas de réponses, et un site déployé sans compte les accepte une fois récupéré.

Types de formulaires

Chaque formulaire est un formulaire de contact ou une liste d’attente. Le type détermine l’affichage de ses réponses sur la page Envois : les lignes d’un formulaire de contact montrent le message, celles d’une liste d’attente montrent qui s’est inscrit et depuis quelle page, et les listes d’attente sont comptées au-dessus du tableau. Les deux envoient le même e-mail de notification.

Lobsite choisit le type au déploiement :

  • Un formulaire où les visiteurs saisissent un e-mail et au plus un nom est une liste d’attente. Les champs cachés, les champs qui commencent par _ et les cases à cocher (une case de consentement) ne comptent pas.
  • C’est aussi le cas d’un formulaire nommé waitlist, newsletter, signup, subscribe, early-access, beta ou notify, quels que soient ses champs.
  • Tout autre formulaire est un formulaire de contact.

Pour choisir vous-même, définissez type dans lobsite.toml :

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

Les inscriptions aux listes d’attente sont gardées tant que le formulaire existe ; les autres réponses le sont pendant la durée de conservation de l’offre (voir Limites).

Formulaire de contact

Une page complète avec un nom, un e-mail et un message. Les libellés et les valeurs autocomplete facilitent la saisie ; les attributs required empêchent l’envoi d’une réponse vide.

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

Pour vérifier les mêmes champs sur le serveur et envoyer les visiteurs vers votre propre page de remerciement, ajoutez le formulaire à lobsite.toml et créez thanks.html :

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

Liste d’attente

Avant le lancement, un champ e-mail suffit. Le nom du formulaire en fait une liste d’attente ; définir type le dit explicitement. Les inscriptions sont comptées sur la page Envois et gardées tant que le formulaire existe.

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

Inscription à une newsletter

Un seul champ suffit. Un deuxième formulaire sur le même site reçoit son propre nom : inscriptions et messages restent séparés sur la page Envois et dans les exports. Un formulaire avec seulement un champ e-mail (et au plus un nom) est une liste d’attente : voir Types de formulaires.

<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 est un champ caché qui choisit la page affichée après l’envoi. Ce doit être un chemin ou une URL du même site ; redirect dans lobsite.toml est prioritaire.

Demande de devis

Listes déroulantes, boutons radio et cases à cocher fonctionnent normalement. Les cases à cocher qui portent le même nom sont enregistrées comme une seule valeur séparée par des virgules.

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

Envoyer sans quitter la page

Pour afficher un message sur place au lieu de charger une nouvelle page, envoyez le formulaire avec fetch. Construisez le corps avec new FormData(form) pour que les champs anti-spam cachés suivent, et demandez du JSON avec l’en-tête 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>

La réponse est {"ok": true}, ou {"ok": false, "errors": {"email": "Required"}} pour les champs refusés, ou {"ok": false, "error": "rate_limited"} (aussi too_large, not_found, forms_off). Sans le script, le même formulaire fonctionne toujours comme un formulaire simple.

Frameworks

React, Vue, Svelte, Astro et les autres fonctionnent quand le formulaire est dans le HTML buildé, ce que produisent le prérendu et l’export statique (Astro et Eleventy par défaut, Next.js avec output: "export", SvelteKit avec prerender, Nuxt avec nuxt generate). Gardez les attributs action et method sur l’élément <form> lui-même.

Dans une application monopage, le formulaire doit être dans le HTML buildé et rester tel qu’il a été servi : un formulaire qui n’existe qu’en JavaScript n’est pas enregistré et ses réponses sont refusées, et un formulaire que le navigateur re-rend perd les champs anti-spam, si bien que ses messages finissent dans les spams.

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

Réglages

Chaque formulaire peut avoir une section dans lobsite.toml. Toutes les clés sont facultatives ; les réglages voyagent avec le déploiement.

[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

Une réponse qui échoue à required ou types n’est pas enregistrée ; le visiteur voit ce qu’il doit corriger et un lien de retour. Avec l’offre gratuite, notify ne peut être que l’e-mail de votre compte, et webhook n’est pas disponible.

Lire les réponses

  • La page Envois de votre tableau de bord montre les réponses de tous les formulaires dans un seul tableau. Recherchez-les, filtrez-les par site et par type de formulaire, et passez aux spams pour voir ce que les vérifications ont intercepté. Une réponse est nouvelle tant que vous ne l’avez pas ouverte.
  • Chaque message est envoyé par e-mail à l’adresse de votre compte, avec Reply-To réglé sur l’expéditeur.
  • lobsite forms ls liste vos formulaires ; lobsite forms export contact --csv télécharge les réponses d’un formulaire. L’export CSV de la page Envois télécharge ce que montre le tableau.

Avec l’offre gratuite, les formulaires fonctionnent en mode limité : un quota mensuel par site, des notifications uniquement vers l’e-mail du compte, et pas de webhooks. L’offre Standard ajoute les webhooks, toute adresse de notification vérifiée et aucun plafond mensuel. Voir Limites.