Contact form for SvelteKit

SvelteKit's form actions are great — but they need a server, which rules out adapter-static. Posting to FormDock from the client keeps your whole site prerenderable while still giving you stored, spam-filtered submissions.

src/lib/ContactForm.svelte
<script>
  let status = "idle";

  async function onSubmit(event) {
    status = "sending";
    const data = Object.fromEntries(new FormData(event.target));
    const res = await fetch("https://formdock.app/f/your-form-key", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    status = res.ok ? "sent" : "error";
  }
</script>

{#if status === "sent"}
  <p>Thanks — we got your message.</p>
{:else}
  <form on:submit|preventDefault={onSubmit}>
    <input name="name" required placeholder="Name" />
    <input name="email" type="email" required placeholder="Email" />
    <textarea name="message" placeholder="Message"></textarea>
    <button disabled={status === "sending"}>Send</button>
    {#if status === "error"}<p>Something went wrong — try again.</p>{/if}
  </form>
{/if}
  • Works with every adapter, including adapter-static with prerender = true — there's no server dependency.
  • For a no-JS fallback, use a plain <form action=... method="POST"> instead and let FormDock redirect to your thanks page.
  • Keep the endpoint in a $env/static/public variable (PUBLIC_FORM_ENDPOINT) rather than hardcoding.

Get your endpoint: create a free FormDock account (100 submissions/month), add a form, and swap your-form-key for the real key.