Skip to content

Integration guide · SvelteKit

A SvelteKit contact form that emails you — no server action required

SvelteKit's form actions are great for data that touches your own database, but a contact form doesn't need one. A plain HTML form pointed at a PostTo endpoint works in a fully static +page.svelte with zero JavaScript, and layers in nicely with use:enhance if you want an inline success state.

PostTo receives the POST, filters spam, emails you the submission, and logs it to a searchable dashboard — your SvelteKit route stays free of a +page.server.ts action.

Free plan, no credit card required.

Three steps, a few minutes

1

Create an endpoint

Sign up free, create an endpoint in the dashboard, and set your destination email. You'll get an endpoint URL right away.

2

Add the form to a route

Drop a plain HTML form into any +page.svelte and set its action to your endpoint URL. No +page.server.ts, no form action, no adapter-specific setup.

3

Optionally enhance it

Add use:enhance to submit via fetch and show an inline success message instead of a full navigation — still no backend code of your own.

The code

Replace YOUR_TOKEN with the endpoint URL from your dashboard.

src/routes/contact/+page.svelte
<script>
  import { enhance } from '$app/forms';
</script>

<form
  method="POST"
  action="https://postto.dev/api/v1/send/YOUR_TOKEN"
  use:enhance={() => {
    return async ({ result, update }) => {
      // result.type is 'success' when PostTo accepts the submission
      await update();
    };
  }}
>
  <input type="text" name="name" placeholder="Name" required />
  <input type="email" name="email" placeholder="Email" required />
  <textarea name="message" required></textarea>

  <!-- Honeypot: bots fill this in, humans never see it -->
  <input type="text" name="_hp" tabindex="-1" autocomplete="off" style="display:none" />

  <!-- Where to send the visitor after a successful submission -->
  <input type="hidden" name="_next" value="https://yoursite.com/thanks" />

  <button type="submit">Send</button>
</form>

Good to know

use:enhance is optional

Without it, the browser does a normal form POST to PostTo and follows the redirect — works even with JavaScript disabled. With it, SvelteKit intercepts the submit for an inline result, but the request still goes straight to PostTo, not through your own server.

No adapter-specific code

Because there's no +page.server.ts action, this works identically under adapter-auto, adapter-static, adapter-node, or any other SvelteKit adapter.

Spam protection is already wired in

The hidden _hp field is a honeypot — humans never see it, bots fill it in, and PostTo silently discards those submissions. Server-side baseline filtering (heuristics and optional AI classification) runs on every submission after that, so you don't need a CAPTCHA to start.

Frequently asked questions

Do I need a +page.server.ts form action?
No — the form posts directly to PostTo, not to your SvelteKit server, so there's no action function to write. A server action only becomes useful if you want to sign the request server-side with the HMAC-signed API.
Does this work with adapter-static?
Yes. The form is plain HTML with no server-side action, so it survives static prerendering unchanged.
Can I show an inline success message instead of redirecting?
Yes — that's what use:enhance is for in the snippet above. Without it, the browser follows PostTo's hosted success page or your own _next URL after a normal form submission.
What does it cost?
The free plan includes 50 submissions per month with the full dashboard — no credit card required. Paid plans start at $9/month.

Add a form to your SvelteKit site today

Create an endpoint, paste the snippet, and see your first submission in the dashboard — all on the free plan.

Try PostTo free