lobsite! Entrar Criar conta

Documentação /

Formulários

Qualquer formulário HTML num site do Lobsite pode receber mensagens: aponte o action dele para /_lobsite/forms/<name> e publique. Não há backend para escrever, script para adicionar nem chave para colar. Os envios chegam à página Envios do seu painel e ao seu e-mail.

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

Como os formulários funcionam

  • O action dá nome ao formulário. /_lobsite/forms/contact é o formulário contact. Os nomes são letras minúsculas, dígitos, - e _. Use um nome por finalidade (contact, newsletter, quote); várias páginas podem compartilhar um formulário.
  • Os formulários são encontrados no deploy. O deploy lê os arquivos HTML e registra cada formulário que envia para /_lobsite/forms/. O formulário precisa estar num arquivo HTML da pasta publicada: um formulário que só existe depois que o JavaScript o renderiza não é encontrado (veja Frameworks).
  • Os campos são guardados com o nome que você deu. Todo campo com name é mantido, como texto. Um campo chamado email é usado como Reply-To do e-mail de notificação e como título na página Envios. Envio de arquivos não é suportado.
  • A proteção contra spam é adicionada para você. Quando a página é servida, um campo-armadilha oculto e um carimbo de tempo assinado são adicionados ao formulário. Envios que preenchem a armadilha ou voltam em menos de 2 segundos ficam separados como spam, e envios demais seguidos de um mesmo visitante são recusados.
  • Depois do envio, o visitante vê uma página de agradecimento com um link de volta, ou a página definida com redirect.
  • Os formulários funcionam nas URLs de produção. Deploys de prévia não aceitam envios, e um site publicado sem conta passa a aceitá-los quando é resgatado.

Tipos de formulário

Cada formulário é um formulário de contato ou uma lista de espera. O tipo define como os envios aparecem na página Envios: as linhas de um formulário de contato mostram a mensagem, as de uma lista de espera mostram quem entrou e de qual página, e as listas de espera são contadas acima da tabela. Os dois enviam o mesmo e-mail de notificação.

O Lobsite escolhe o tipo no deploy:

  • Um formulário em que os visitantes preenchem um e-mail e no máximo um nome é uma lista de espera. Campos ocultos, campos que começam com _ e caixas de seleção (um consentimento) não contam.
  • Também é o caso de um formulário chamado waitlist, newsletter, signup, subscribe, early-access, beta ou notify, sejam quais forem os campos.
  • Todo outro formulário é um formulário de contato.

Para escolher você mesmo, defina type no lobsite.toml:

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

As inscrições em listas de espera ficam guardadas enquanto o formulário existir; os demais envios, pelo período de retenção do plano (veja Limites).

Formulário de contato

Uma página completa com nome, e-mail e mensagem. Os rótulos e os valores de autocomplete facilitam o preenchimento; os atributos required barram um envio vazio antes de ele sair.

<!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 verificar os mesmos campos no servidor e mandar os visitantes para a sua própria página de agradecimento, adicione o formulário ao lobsite.toml e crie thanks.html:

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

Lista de espera

Antes do lançamento, um campo de e-mail basta. O nome do formulário o torna uma lista de espera; definir type diz isso explicitamente. As inscrições são contadas na página Envios e guardadas enquanto o formulário existir.

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

Inscrição em newsletter

Um campo basta. Um segundo formulário no mesmo site ganha o próprio nome, então inscrições e mensagens ficam separadas na página Envios e nas exportações. Um formulário só com um campo de e-mail (e no máximo um nome) é uma lista de espera: veja Tipos de formulário.

<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 é um campo oculto que escolhe a página mostrada depois do envio. Precisa ser um caminho ou uma URL do mesmo site; redirect no lobsite.toml tem prioridade.

Pedido de orçamento

Listas de seleção, botões de opção e caixas de seleção funcionam normalmente. Caixas com o mesmo nome são guardadas como um único valor separado por vírgulas.

<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 sem sair da página

Para mostrar uma mensagem no lugar em vez de carregar uma nova página, envie o formulário com fetch. Monte o corpo com new FormData(form) para que os campos ocultos antispam sigam junto, e peça JSON com o cabeçalho 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>

A resposta é {"ok": true}, ou {"ok": false, "errors": {"email": "Required"}} para os campos que não passaram, ou {"ok": false, "error": "rate_limited"} (também too_large, not_found, forms_off). Sem o script, o mesmo formulário continua funcionando como um formulário comum.

Frameworks

React, Vue, Svelte, Astro e os demais funcionam quando o formulário está no HTML gerado, que é o que a pré-renderização e a exportação estática produzem (Astro e Eleventy por padrão, Next.js com output: "export", SvelteKit com prerender, Nuxt com nuxt generate). Mantenha os atributos action e method no próprio elemento <form>.

Numa aplicação de página única, o formulário precisa estar no HTML gerado e continuar como foi servido: um formulário que só existe em JavaScript não é registrado e os envios dele são recusados, e um formulário que o navegador renderiza de novo perde os campos antispam, então as mensagens dele vão para o 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>
  );
}

Configurações

Cada formulário pode ter uma seção no lobsite.toml. Todas as chaves são opcionais; as configurações vão junto com o 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

Um envio que falha em required ou types não é guardado; o visitante vê o que corrigir e um link de volta. No plano gratuito, notify só pode ser o e-mail da sua conta e webhook não está disponível.

Lendo os envios

  • A página Envios do painel mostra os envios de todos os formulários numa única tabela. Pesquise, filtre por site e por tipo de formulário, e mude para spam para ver o que as verificações pegaram. Um envio é novo até você abri-lo.
  • Cada mensagem é enviada por e-mail para o endereço da sua conta, com Reply-To definido como o remetente.
  • lobsite forms ls lista seus formulários; lobsite forms export contact --csv baixa os envios de um formulário. Exportar CSV na página Envios baixa o que a tabela mostra.

No plano gratuito, os formulários rodam em modo limitado: uma cota mensal por site, notificações só para o e-mail da conta e sem webhooks. O plano Standard adiciona webhooks, qualquer endereço de notificação verificado e nenhum limite mensal. Veja Limites.