# Quickstart: Browser (frontend-only)

> Send email from frontend JavaScript with a public key that can't be abused: the recipient lives in the server-stored template, never in your page's code.

Canonical: https://emailfast.dev/docs/quickstart-browser

## 1. Install and send

```bash
npm install @email-fast/browser
```

```js
import emailjs from "@email-fast/browser";

emailjs.init({ publicKey: "ef_pub_..." }); // safe to ship — see below

await emailjs.send("default", "template_contact", {
  name: "Ada",
  message: "Interested in the ledger product.",
  reply_to: "ada@example.com",
});
```

Or bind a whole form in one call — field names become template params:

```js
document.querySelector("#contact").addEventListener("submit", (e) => {
  e.preventDefault();
  emailjs.sendForm("default", "template_contact", e.target);
});
```

The API is EmailJS-compatible (same `init`/`send`/`sendForm` signatures), so
[migrating from EmailJS](/migrate/emailjs) is an import swap.

## 2. Why a public key in your HTML is safe here

An `ef_pub_` key is visible to every visitor, so the design assumes it is
stolen: 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.

That one rule — recipient from the template, never from the request — is what
makes the key shippable. `template_params` fills placeholders in *your* template
addressed to *your* inbox; there is no parameter that redirects mail. Around it:

- **Origin allowlist.** In the dashboard, list the origins allowed to use the
  key (`https://yourdomain.com`). Requests from other origins are refused, so a
  copied key is dead weight on someone else's site.
- **Typed variable schema.** Each template declares its parameters and their
  types. Unknown keys are stripped, wrong types rejected — a hostile
  `template_params` can't inject markup or oversized junk.
- **Rate caps.** Per-key caps bound what a script in a loop can burn.

## 3. Test without sending anything

Point the template at a sandbox project while you build: sandbox keys (ef_sandbox_…) that run the real pipeline dry: real validation, real rendering, real events, a hosted capture inbox — and no email leaves.
Submit your form, open the capture inbox, and see exactly what would have been
delivered.

## When you outgrow frontend-only

Server-side sends get the full REST API with explicit `idempotency_key` support —
start with the [Node.js quickstart](/docs/quickstart-node).

## Next

- [Frontend email, done safely](/features/frontend)
- [Migrate from EmailJS](/migrate/emailjs)
- [All docs](/docs)
