Svelte & SvelteKit

Wire a Svelte component to your Formcrest endpoint — with plain fetch or the framework-agnostic @formcrest/sdk submit() function.

Plain HTML works too

A Svelte component can render a plain <form action> pointed at the endpoint and let the browser handle everything — see Plain HTML. The rest of this guide covers AJAX submissions with an in-page success state.

A Svelte 5 component

Post a FormData with the Accept: application/json header. Keep the hidden _honey field in your markup — it's our spam honeypot.

<script>
  let status = $state("idle"); // idle | submitting | success | error
  let message = $state("");

  async function onsubmit(event) {
    event.preventDefault();
    status = "submitting";

    const response = await fetch(
      "https://api.formcrest.com/v1/submit/abc123",
      {
        method: "POST",
        headers: { Accept: "application/json" },
        body: new FormData(event.target),
      },
    ).catch(() => null);

    if (response?.ok) {
      status = "success";
    } else {
      status = "error";
      const body = await response?.json().catch(() => null);
      message = body?.message ?? "Something went wrong. Please try again.";
    }
  }
</script>

{#if status === "success"}
  <p>Thanks — we'll be in touch.</p>
{:else}
  <form {onsubmit}>
    <input type="email" name="email" required />
    <textarea name="message" required></textarea>

    <!-- Honeypot — keep it hidden from real users. -->
    <input
      type="text"
      name="_honey"
      tabindex="-1"
      autocomplete="off"
      style="display: none"
    />

    <button type="submit" disabled={status === "submitting"}>
      {status === "submitting" ? "Sending…" : "Send"}
    </button>
    {#if status === "error"}
      <p role="alert">{message}</p>
    {/if}
  </form>
{/if}

On Svelte 4, swap the runes for plain reactive variables (let status = "idle" and on:submit|preventDefault) — the fetch logic is identical.

Using the SDK instead

The submit() function from @formcrest/sdk is framework-agnostic and never throws — network failures come back as a result object:

npm install @formcrest/sdk
import { submit } from "@formcrest/sdk";

async function onsubmit(event) {
  event.preventDefault();
  status = "submitting";

  const result = await submit("abc123", new FormData(event.target));

  if (result.ok) {
    status = "success";
  } else {
    status = "error";
    message = result.message;
    // result.fieldErrors?.email, etc.
  }
}

SvelteKit

The component is purely client-side, so it drops into any SvelteKit page — including prerendered ones — without a form action or server route. If you prefer SvelteKit's progressive enhancement, the plain-HTML approach degrades gracefully: the form posts directly to Formcrest and the visitor is redirected to your success URL.

Next steps