Email Fast Get a sandbox key
Guides

Send email with Svelte

Send from a component with a public key, or from a SvelteKit form action with a secret one.

Facts verified 2026-07-17 — corrections: hello@emailfast.dev

A Svelte component can send email straight from the browser. Email Fast ships a browser SDK with EmailJS-compatible endpoints — the recipient always comes from the server-stored template, never from the request, so a public key in your frontend can't be abused to spam arbitrary addresses. For a static Svelte site that is the whole answer; on SvelteKit you can instead keep a secret key in a server-only form action — both patterns below.

npm install @email-fast/browser
<!-- ContactForm.svelte -->
<script>
  import emailfast from "@email-fast/browser";

  emailfast.init({ publicKey: "ef_pub_..." }); // public by design — safe to ship

  let state = "idle";

  async function submit(event) {
    event.preventDefault();
    state = "sending";
    try {
      await emailfast.sendForm("default", "contact_form", event.target);
      state = "sent";
    } catch {
      state = "error";
    }
  }
</script>

<form on:submit={submit}>
  <input name="name" required />
  <input name="email" type="email" required />
  <textarea name="message" required />
  <button disabled={state === "sending"}>Send</button>
  {#if state === "sent"}<p>Thanks — we got it.</p>{/if}
  {#if state === "error"}<p>That didn't go through. Try again.</p>{/if}
</form>

Or: a SvelteKit form action

On SvelteKit, $env/static/private guarantees the key can never reach the client:

// src/routes/contact/+page.server.js
import { EMAILFAST_API_KEY } from "$env/static/private"; // ef_sandbox_… while testing
import { EmailFast } from "@email-fast/nodejs";

const ef = new EmailFast({ apiKey: EMAILFAST_API_KEY, baseUrl: "https://api.emailfast.dev" });

export const actions = {
  default: async ({ request }) => {
    const form = await request.formData();
    await ef.send({
      to: "team@yourdomain.dev",
      subject: "New contact message",
      html: "<p>{{message}}</p>",
      data: { message: String(form.get("message")) },
      idempotency_key: `contact-${form.get("formId")}`, // hidden field set once per render
    });
    return { ok: true };
  },
};

Gotchas

Next

See it for yourself

Sandbox keys run the real pipeline dry — real validation, real events, a hosted inbox, no email sent. Early access is onboarding now.