Blog

SvelteKit Forms Without the Form Actions Boilerplate

Skip SvelteKit's +page.server.ts form actions for a simple contact form — submit the form directly to an external endpoint like FormBridge instead.

← Back to the blog
AI Powered

Explore this article with AI

Get an instant summary, key takeaways, action items, and answers to your questions about this article.

Choose your AI assistant
ChatGPT Perplexity
Quick answer

For a contact form whose only job is sending an email, you can skip SvelteKit's +page.server.ts form actions entirely and set the form's action attribute directly to an external endpoint like a FormBridge form URL — form actions are for logic that needs to run on your own server, which a simple contact form doesn't.

Form actions solve a different problem

SvelteKit's form actions (export const actions in a +page.server.ts) exist so a form can run trusted logic on your own server — write to a database, check a session, redirect based on business rules. They're one of SvelteKit's best features. They're also more machinery than a contact form needs if the form's only job is "send this to someone's inbox."

If that's all you need, you can skip +page.server.ts entirely and submit straight to an external endpoint.

The form

<!-- src/routes/contact/+page.svelte -->
<script>
  let sending = false
</script>

<form
  action="https://app.formbridge.ai/api/forms/fb_8h2k9p"
  method="POST"
  on:submit={() => (sending = true)}
>
  <label for="full-name">Full name</label>
  <input id="full-name" name="full-name" type="text" required />

  <label for="email">Email</label>
  <input id="email" name="email" type="email" required />

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="5" required></textarea>

  <button type="submit" disabled={sending}>
    {sending ? 'Sending…' : 'Send message'}
  </button>
</form>

That's the entire route. No +page.server.ts, no actions object, no fail() or redirect() calls to write, and nothing added to load to support it.

Why this works cleanly with SvelteKit specifically

Form actions are built around the assumption that the destination is your own app — that's the whole value: SvelteKit progressively enhances the submission, gives you typed form data back in the component, and can redirect on success. None of that applies when the destination is a URL outside your app entirely. Submitting to FormBridge is a plain cross-origin POST, so use:enhance — which wires up your own action's progressive enhancement — isn't the right tool here, because you're not calling your own action at all.

If you later want an inline success message instead of a full navigation, add a small on:submit handler that calls preventDefault() and does its own fetch() — but that's an incremental upgrade, not a requirement to get the form working.

What you keep

Everything SvelteKit gives you for free still applies: the route is prerenderable, the page ships no more JS than the tiny sending toggle needs, and there's no server-side code in your app tied to sending email at all.

Frequently asked

When should I use a SvelteKit form action instead of an external endpoint?

When the form needs to run logic that only your server can do — checking a session, writing to your own database, controlling a redirect based on business rules. A form that just needs to email someone doesn't need any of that.

Does use:enhance work when submitting to an external URL?

use:enhance progressively enhances a call to your own SvelteKit form action, so it isn't the relevant tool when the form's action points at a URL outside your app — that's a plain cross-origin POST instead.

Do I lose SvelteKit's benefits by skipping form actions here?

No. The page can still be prerendered and ships minimal JavaScript; you're only skipping the +page.server.ts file, not any client-side SvelteKit feature.

Key facts

  • SvelteKit form actions are defined by exporting an actions object from a +page.server.ts file colocated with a route.
  • A form element's action attribute can point at any URL, including one outside the SvelteKit app, bypassing +page.server.ts entirely.
  • SvelteKit's use:enhance directive progressively enhances submissions to the app's own form actions and does not apply to a plain cross-origin POST.

Terms in this post

Form action
In SvelteKit, a named function exported from actions in +page.server.ts that runs on the server when a <form> on that route is submitted.

Get the next one in your inbox.

One email when we publish something worth reading. No spam — appropriately enough, we'd know.