Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Submit any HTML form through VBService('email') using a named template. Progressive enhancement on top of native form action.
Add data-vb-email-form="template-name" to any <form> to intercept its submit and POST { to, template, data } to /go/email via VBService('email'). The template name maps to a renderer registered in your backend (see the /go/email template registry).
Progressive enhancement. Without JS the form falls back to its native action attribute, so the same markup works as a server-side form post. With JS the submission goes through /go/email — one indirection layer between the form and whichever provider (Sendgrid, Postmark, SES, …) sits behind the endpoint.
<form action="/contact" method="POST" data-vb-email-form="contact-form" data-vb-email-to="[email protected]"> <form-field> <label for="name">Name</label> <input type="text" id="name" name="name" required autocomplete="name"/> </form-field> <form-field> <label for="email">Email</label> <input type="email" id="email" name="email" required autocomplete="email"/> </form-field> <form-field> <label for="subject">Subject</label> <input type="text" id="subject" name="subject"/> </form-field> <form-field> <label for="message">Message</label> <textarea id="message" name="message" rows="5" required></textarea> </form-field> <output data-vb-email-status aria-live="polite"></output> <button type="submit">Send</button></form>
| Attribute | Required | Purpose |
|---|---|---|
data-vb-email-form | yes | Template name. Must match a renderer registered server-side. VB names four built-ins: contact-form, page-watch-update, goodurl-digest, newsletter-welcome. |
data-vb-email-to | typically | Recipient email. If omitted, the script looks for a form field named to or email; failing that the backend determines the recipient (e.g. a configured contact-form inbox). |
data-vb-email-loading-label | no | Replaces the submit button label while the request is in flight (e.g. "Sending…"). |
data-vb-email-success | no | Message shown inside [data-vb-email-status] on 2xx. Default: “Sent. Thank you.” |
data-vb-email-error | no | Message shown inside [data-vb-email-status] on failure. Default: “Sorry, the message could not be sent. Try again.” |
data-vb-email-no-reset | no | Skip the automatic form.reset() on success. |
Place an element with data-vb-email-status anywhere inside the form. The script writes the success or error message into it and toggles data-state="success" or data-state="error", so you can style each state with CSS:
[data-vb-email-status][data-state="success"] { color: var(--color-success); }[data-vb-email-status][data-state="error"] { color: var(--color-error); }
An <output aria-live="polite"> is the natural element — screen readers announce the status without stealing focus.
| Event | Detail | When |
|---|---|---|
vb-email-form:submitting | { template } | Just before the request goes out |
vb-email-form:success | { id } | 2xx response (id is whatever the backend returns) |
vb-email-form:error | { error, status?, body? } | Network failure or non-2xx response |
All three bubble and cross shadow boundaries so a parent app can listen at the document level.
The Pages Function at functions/go/email.js (and the Cloudflare reference at admin/reference-implementations/cloudflare/) accepts the contract as-is and dispatches to a configured transport (Resend by default, fallback to record-only when secrets are absent). Wire any other provider by following the reference implementations as templates.