send.webforms.toRead the docs →

Static site generators

Add a contact form to a Vite app

Vite builds a static bundle, so there is no server in the output to handle a form. That is fine: post straight to an endpoint from the client. Put the URL in an env var so dev and production can point at different forms, and keep the submit logic in one module you can import from any component.

Get an endpointRead the docs

Setup

  1. Add the endpoint to .env

    Vite only exposes variables prefixed with VITE_ to client code.

  2. Write a submit helper

    One module, importable from vanilla JS or any framework you are using with Vite.

  3. Call it from your component

    The helper returns the parsed JSON response.

Vite examples

Swap in your own endpoint and these run as-is.

.env
VITE_FORM_ENDPOINT=https://send.webforms.to/wft_your_key
src/submit.js
const ENDPOINT = import.meta.env.VITE_FORM_ENDPOINT;

export async function submitForm(form) {
  const res = await fetch(ENDPOINT, {
    method: "POST",
    headers: { accept: "application/json" },
    body: new FormData(form),
  });

  return res.json();
}

Vanilla usage. Import the same helper from a React, Vue or Svelte component instead if you are using one.

src/main.js
import { submitForm } from "./submit.js";

const form = document.querySelector("#contact");
const result = document.querySelector("#result");

form.addEventListener("submit", async (e) => {
  e.preventDefault();
  const data = await submitForm(form);
  result.textContent = data.ok ? "Thanks, we got it." : data.message;
  if (data.ok) form.reset();
});

Worth knowing

Vite form FAQ

Yes. Those variables are baked into the public bundle, and the submit key is public by design. Restrict which domains may post to the form in the dashboard rather than trying to hide the key.

Ready to wire up your Vite form?

Free for 300 submissions a month. Endpoint in under a minute, no card required.

Start free