lobsite! Iniciar sesión Registrarse

Docs /

Formularios

Cualquier formulario HTML de un sitio de Lobsite puede recoger mensajes: apunta su action a /_lobsite/forms/<name> y despliega. No hay backend que escribir, script que añadir ni clave que pegar. Los envíos llegan a la página Envíos de tu panel y a tu correo.

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

Cómo funcionan los formularios

  • El action da nombre al formulario. /_lobsite/forms/contact es el formulario contact. Los nombres son letras minúsculas, dígitos, - y _. Usa un nombre por propósito (contact, newsletter, quote); varias páginas pueden compartir un formulario.
  • Los formularios se detectan al desplegar. El deploy lee los archivos HTML y registra cada formulario que envía a /_lobsite/forms/. El formulario tiene que estar en un archivo HTML de la carpeta desplegada: un formulario que solo existe después de que JavaScript lo renderice no se detecta (consulta Frameworks).
  • Los campos se guardan con el nombre que les pones. Cada campo con name se conserva, como texto. Un campo llamado email se usa como Reply-To del correo de aviso y como título en la página Envíos. La subida de archivos no está disponible.
  • La protección contra spam se añade por ti. Al servir la página, se añade al formulario un campo trampa oculto y una marca de tiempo firmada. Los envíos que rellenan la trampa o vuelven en menos de 2 segundos se apartan como spam, y se rechazan demasiados seguidos de un mismo visitante.
  • Tras enviar, el visitante ve una página de agradecimiento con un enlace para volver, o la página que configures con redirect.
  • Los formularios funcionan en las URL de producción. Los deploys de vista previa no aceptan envíos, y un sitio desplegado sin cuenta los acepta cuando se reclama.

Tipos de formulario

Cada formulario es un formulario de contacto o una lista de espera. El tipo decide cómo se muestran sus envíos en la página Envíos: las filas de un formulario de contacto muestran el mensaje, las de una lista de espera muestran quién se apuntó y desde qué página, y las listas de espera se cuentan encima de la tabla. Ambos envían el mismo correo de aviso.

Lobsite elige el tipo al desplegar:

  • Un formulario en el que los visitantes rellenan un correo y como mucho un nombre es una lista de espera. Los campos ocultos, los campos que empiezan por _ y las casillas (una de consentimiento) no cuentan.
  • También lo es un formulario llamado waitlist, newsletter, signup, subscribe, early-access, beta o notify, tenga los campos que tenga.
  • Cualquier otro formulario es un formulario de contacto.

Para elegirlo tú, define type en lobsite.toml:

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

Las inscripciones en listas de espera se conservan mientras exista el formulario; los demás envíos, durante el periodo de conservación del plan (consulta Límites).

Formulario de contacto

Una página completa con nombre, correo y mensaje. Las etiquetas y los valores autocomplete facilitan rellenarlo; los atributos required frenan un envío vacío antes de mandarlo.

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

Para comprobar los mismos campos en el servidor y llevar a los visitantes a tu propia página de agradecimiento, añade el formulario a lobsite.toml y crea thanks.html:

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

Lista de espera

Antes del lanzamiento, basta con un campo de correo. El nombre del formulario lo convierte en lista de espera; definir type lo dice de forma explícita. Las inscripciones se cuentan en la página Envíos y se conservan mientras exista el formulario.

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

Suscripción a newsletter

Un campo es suficiente. Un segundo formulario en el mismo sitio lleva su propio nombre, así que inscripciones y mensajes se mantienen separados en la página Envíos y en las exportaciones. Un formulario con solo un campo de correo (y como mucho un nombre) es una lista de espera: consulta Tipos de formulario.

<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 es un campo oculto que elige la página mostrada tras enviar. Debe ser una ruta o una URL del mismo sitio; redirect en lobsite.toml tiene prioridad.

Solicitud de presupuesto

Los desplegables, botones de opción y casillas funcionan como siempre. Las casillas con el mismo nombre se guardan como un único valor separado por comas.

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

Enviar sin salir de la página

Para mostrar un mensaje en el sitio en lugar de cargar una página nueva, envía el formulario con fetch. Construye el cuerpo con new FormData(form) para que vayan los campos ocultos antispam, y pide JSON con la cabecera 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 respuesta es {"ok": true}, o {"ok": false, "errors": {"email": "Required"}} para los campos que no pasaron, o {"ok": false, "error": "rate_limited"} (también too_large, not_found, forms_off). Sin el script, el mismo formulario sigue funcionando como un formulario normal.

Frameworks

React, Vue, Svelte, Astro y los demás funcionan cuando el formulario está en el HTML compilado, que es lo que producen el prerenderizado y la exportación estática (Astro y Eleventy por defecto, Next.js con output: "export", SvelteKit con prerender, Nuxt con nuxt generate). Mantén los atributos action y method en el propio elemento <form>.

En una aplicación de una sola página, el formulario tiene que estar en el HTML compilado y quedarse tal como se sirvió: un formulario que solo existe en JavaScript no se registra y sus envíos se rechazan, y un formulario que el navegador vuelve a renderizar pierde los campos antispam, así que sus mensajes acaban en spam.

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

Ajustes

Cada formulario puede tener una sección en lobsite.toml. Todas las claves son opcionales; los ajustes viajan con el deploy.

[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

Un envío que no cumple required o types no se guarda; el visitante ve qué corregir y un enlace para volver. En el plan gratuito, notify solo puede ser el correo de tu cuenta y webhook no está disponible.

Leer los envíos

  • La página Envíos de tu panel muestra los envíos de todos los formularios en una tabla. Búscalos, fíltralos por sitio y por tipo de formulario, y cambia a spam para ver lo que atraparon las comprobaciones. Un envío es nuevo hasta que lo abres.
  • Cada mensaje se envía por correo a la dirección de tu cuenta, con Reply-To del remitente.
  • lobsite forms ls lista tus formularios; lobsite forms export contact --csv descarga los envíos de un formulario. Exportar CSV en la página Envíos descarga lo que muestra la tabla.

En el plan gratuito, los formularios funcionan en modo limitado: una cuota mensual por sitio, avisos solo al correo de tu cuenta y sin webhooks. El plan Standard añade webhooks, cualquier dirección de aviso verificada y sin límite mensual. Consulta Límites.