Формы
Любая HTML-форма на сайте в Lobsite может собирать сообщения: направьте её action на /_lobsite/forms/<name> и задеплойте. Не нужно писать бэкенд, подключать скрипт и вставлять ключ. Заявки приходят на страницу «Заявки» в панели и на почту.
<form action="/_lobsite/forms/contact" method="POST">
<input name="email" type="email" required>
<textarea name="message" required></textarea>
<button>Send</button>
</form>
Как работают формы
- Action задаёт имя формы.
/_lobsite/forms/contact— это формаcontact. Имена состоят из строчных букв, цифр,-и_. Используйте одно имя на одну задачу (contact,newsletter,quote); несколько страниц могут делить одну форму. - Формы находятся при деплое. Деплой читает HTML-файлы и регистрирует каждую форму, которая отправляет данные на
/_lobsite/forms/. Форма должна быть в HTML-файле в деплоемой папке: форма, которая появляется только после отрисовки JavaScript, не будет найдена (см. Фреймворки). - Поля сохраняются под вашими именами. Каждое поле с
nameсохраняется как текст. Поле с именемemailиспользуется как Reply-To в письме-уведомлении и как заголовок на странице «Заявки». Загрузка файлов не поддерживается. - Защита от спама добавляется за вас. Когда страница отдаётся, в форму добавляются скрытое поле-ловушка и подписанная метка времени. Заявки, заполнившие ловушку или пришедшие в течение 2 секунд, откладываются как спам, а слишком частые заявки от одного посетителя отклоняются.
- После отправки посетитель видит страницу благодарности со ссылкой назад или страницу, заданную в
redirect. - Формы работают на рабочих URL. Деплои предпросмотра не принимают заявки, а сайт, задеплоенный без аккаунта, начинает принимать их после того, как его заберут.
Типы форм
Каждая форма — это форма обратной связи или лист ожидания. Тип определяет, как её заявки показываются на странице «Заявки»: в строках формы обратной связи видно сообщение, в строках листа ожидания — кто записался и с какой страницы, а листы ожидания подсчитываются над таблицей. Оба типа отправляют одинаковое письмо-уведомление.
Lobsite выбирает тип при деплое:
- Форма, в которую посетители вводят email и максимум имя, — это лист ожидания. Скрытые поля, поля, начинающиеся с
_, и флажки (согласие) не учитываются. - Им же считается форма с именем
waitlist,newsletter,signup,subscribe,early-access,betaилиnotify, какие бы поля в ней ни были. - Любая другая форма — форма обратной связи.
Чтобы выбрать самому, задайте type в lobsite.toml:
[forms.launch]
type = "waitlist" # or "contact"
Записи в листы ожидания хранятся, пока существует форма; остальные заявки — в течение срока хранения по тарифу (см. Ограничения).
Форма обратной связи
Полная страница с именем, email и сообщением. Подписи и значения autocomplete упрощают заполнение; атрибуты required не дают отправить пустую заявку.
<!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>
Чтобы проверять те же поля на сервере и отправлять посетителей на свою страницу благодарности, добавьте форму в lobsite.toml и создайте thanks.html:
[forms.contact]
required = ["name", "email", "message"]
types = { email = "email" }
redirect = "/thanks"
Лист ожидания
До запуска достаточно поля для email. Имя формы делает её листом ожидания; type прямо это указывает. Записи подсчитываются на странице «Заявки» и хранятся, пока существует форма.
<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" }
Подписка на рассылку
Одного поля достаточно. Вторая форма на том же сайте получает своё имя, поэтому подписки и сообщения разделены на странице «Заявки» и в выгрузках. Форма только с полем email (и максимум именем) — это лист ожидания: см. Типы форм.
<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 — скрытое поле, которое выбирает страницу после отправки. Это должен быть путь или URL на том же сайте; redirect в lobsite.toml имеет приоритет.
Запрос расчёта стоимости
Выпадающие списки, переключатели и флажки работают как обычно. Флажки с одинаковым именем сохраняются как одно значение через запятую.
<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>
Отправка без ухода со страницы
Чтобы показать сообщение на месте, а не загружать новую страницу, отправьте форму через fetch. Соберите тело через new FormData(form), чтобы скрытые антиспам-поля ушли вместе с ним, и запросите JSON заголовком 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>
Ответ — {"ok": true}, или {"ok": false, "errors": {"email": "Required"}} для полей, не прошедших проверку, или {"ok": false, "error": "rate_limited"} (а также too_large, not_found, forms_off). Без скрипта та же форма продолжает работать как обычная.
Фреймворки
React, Vue, Svelte, Astro и остальные работают, если форма есть в собранном HTML — его дают пререндеринг и статический экспорт (Astro и Eleventy по умолчанию, Next.js с output: "export", SvelteKit с prerender, Nuxt с nuxt generate). Оставляйте атрибуты action и method на самом элементе <form>.
В одностраничном приложении форма должна быть в собранном HTML и оставаться в том виде, в каком пришла: форма, существующая только в JavaScript, не регистрируется, и её заявки отклоняются, а форма, которую браузер перерисовал, теряет антиспам-поля, поэтому её сообщения попадают в спам.
// 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>
);
}
Настройки
У каждой формы может быть раздел в lobsite.toml. Все ключи необязательны; настройки едут вместе с деплоем.
[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
Заявка, не прошедшая required или types, не сохраняется; посетитель видит, что исправить, и ссылку назад. На бесплатном тарифе notify может быть только почтой вашего аккаунта, а webhook недоступен.
Чтение заявок
- Страница «Заявки» в панели показывает заявки всех форм в одной таблице. Ищите по ним, фильтруйте по сайту и типу формы и переключайтесь на спам, чтобы увидеть, что отсеяли проверки. Заявка считается новой, пока вы её не откроете.
- Каждое сообщение приходит на почту вашего аккаунта с Reply-To, указывающим на отправителя.
lobsite forms lsвыводит список ваших форм;lobsite forms export contact --csvскачивает заявки одной формы. Экспорт в CSV на странице «Заявки» скачивает то, что показывает таблица.
На бесплатном тарифе формы работают в ограниченном режиме: месячная квота на сайт, уведомления только на почту аккаунта и без вебхуков. Тариф Standard добавляет вебхуки, любой подтверждённый адрес для уведомлений и снимает месячное ограничение. См. Ограничения.