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áriocontact. 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 chamadoemailé 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,betaounotify, 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 lslista seus formulários;lobsite forms export contact --csvbaixa 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.