send.webforms.toRead the docs →

Frameworks and libraries

Add a contact form to a Svelte app

Svelte's form story is unusually good: SvelteKit actions with use:enhance give you progressive enhancement almost for free. What it does not give you is somewhere for the data to go. WebForms is that somewhere. Below: a plain Svelte component using runes, and a SvelteKit action that forwards the submission server-side.

Get an endpointRead the docs

Setup

  1. Copy your endpoint

    Create a form in the dashboard. The endpoint is the only configuration you need.

  2. Pick client or server

    Plain Svelte posts from the browser. SvelteKit can post from a form action instead if you prefer everything to go through your server.

  3. Add destinations

    Email, Slack, Discord, Telegram, webhooks: configured in the dashboard, changed without a redeploy.

Svelte examples

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

Svelte 5 runes, posting from the browser.

src/lib/ContactForm.svelte
<script>
  let status = $state("idle");
  let error = $state(null);

  async function onSubmit(e) {
    status = "sending";

    const res = await fetch("https://send.webforms.to/wft_your_key", {
      method: "POST",
      headers: { accept: "application/json" },
      body: new FormData(e.currentTarget),
    });

    const data = await res.json();

    if (data.ok) {
      status = "sent";
    } else {
      error = data.message;
      status = "error";
    }
  }
</script>

{#if status === "sent"}
  <p role="status">Thanks, we got it.</p>
{:else}
  <form onsubmit={(e) => { e.preventDefault(); onSubmit(e); }}>
    <input name="name" required />
    <input name="email" type="email" required />
    <textarea name="message" required></textarea>
    <button disabled={status === "sending"}>Send</button>
    {#if error}<p role="alert">{error}</p>{/if}
  </form>
{/if}

SvelteKit form action. Pair it with use:enhance for progressive enhancement.

src/routes/contact/+page.server.js
import { fail, redirect } from "@sveltejs/kit";

export const actions = {
  default: async ({ request }) => {
    const formData = await request.formData();

    const res = await fetch("https://send.webforms.to/wft_your_key", {
      method: "POST",
      headers: { accept: "application/json" },
      body: formData,
    });

    const data = await res.json();
    if (!data.ok) {
      return fail(400, { message: data.message ?? "Submission failed" });
    }

    redirect(303, "/contact/thanks");
  },
};

Worth knowing

Svelte form FAQ

Both work. A form action gives you progressive enhancement and keeps the endpoint off the client; a browser fetch preserves per-visitor spam signals like IP and fill time.

Where Svelte submissions can go

The guide above gets the submission to your endpoint. From there it can land anywhere: one destination on Free, several on Pro.

Need the form markup too? The template gallery has complete forms for contact, waitlist, job application and more, and the form generator builds one field by field.

Ready to wire up your Svelte form?

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

Start free