← All posts

Build a SvelteKit contact form in minutes

Add a working contact form to a SvelteKit app with a one-line email action — no API routes to hand-roll, no email HTML to write. A step-by-step guide with Postboi.

A contact form is the most common reason to add email to a web app, and in SvelteKit it's also one of the quickest things you can build. With Postboi the entire server side is a single line, and the email body writes itself from your form fields.

Here's the whole thing, start to finish.

1. Set up Postboi

Run the CLI — it signs you in, writes a token, and installs Postboi:

terminal
bunx postboi init

2. The server action — one line

postboi/kit reads the submitted FormData, sends it, and returns { success: true } — or fail(400, { error }) if something goes wrong. Wire it up as your default form action:

+page.server.ts
import { mail } from 'postboi/kit'

export const actions = { default: mail }

That's the entire back end. No API route, no request parsing, no email template.

3. The form

Point a multipart/form-data form at the action. Field names use fieldset→field syntax to group related fields, and _subject sets the email subject. A hidden _reply_to field means hitting Reply in your inbox goes straight back to the sender:

+page.svelte
<script lang="ts">
	import { enhance } from '$app/forms'

	let email = $state('')
</script>

<form method="POST" use:enhance enctype="multipart/form-data">
	<input type="hidden" name="_subject" value="Contact Form" />
	<input type="hidden" name="_reply_to" value={email} />
	<input name="contact→name" placeholder="Name" required />
	<input name="contact→email" type="email" placeholder="Email" required bind:value={email} />
	<textarea name="details→message" placeholder="Message"></textarea>
	<input type="file" name="details→attachments" multiple />
	<button type="submit">Send</button>
</form>

That's it: a fully working SvelteKit contact form with file uploads and sensible reply-to behaviour.

4. What lands in your inbox

Submit that form and here's the email. Each fieldset→field group becomes a heading with a table of its fields, files arrive as attachments, and hitting Reply goes straight back to the sender — all without writing any email markup:

Keep going

Postboi is framework-agnostic, so the same one-line approach works in Next.js, Astro, Nuxt, Remix, and more. Postboi is currently in pre-release — pin your version and check the changelog before upgrading.

Start sending — free.

The Postboi mascot

Put the boi to work.

One command between you and your first delivered email.

Start sending — free