Skip to main content
Svelte & SvelteKit·Lesson 4 of 5

Forms & Actions

SvelteKit's form actions let you handle form submissions on the server using plain HTML <form> elements. They work without JavaScript (progressive enhancement) and enhance progressively when JS is available.

Defining an Action

Actions live in +page.server.js alongside your load function:

Ctrl+Enter
HTML
CSS
JS
Preview

The Form Template

<!-- src/routes/contact/+page.svelte -->
<script>
  export let form;  // contains action return value (errors, data)
</script>

<form method="POST">
  {#if form?.error}
    <p class="error">{form.error}</p>
  {/if}

  <label>
    Name
    <input name="name" value={form?.name ?? ''} required>
  </label>

  <label>
    Email
    <input name="email" type="email" value={form?.email ?? ''} required>
  </label>

  <label>
    Message
    <textarea name="message">{form?.msg ?? ''}</textarea>
  </label>

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

With no JavaScript, this is a full round-trip: form submits → server validates → redirects or returns errors. It works in any browser, including with JavaScript disabled.

Progressive Enhancement with use:enhance

Add use:enhance to intercept the submission with fetch, keeping the page without a full reload:

<script>
  import { enhance } from '$app/forms';
  export let form;

  let loading = false;
</script>

<form method="POST" use:enhance={()=> {
  loading= true;
  return async ({ update })=> {
    await update();
    loading= false;
  };
}}>
  <button disabled={loading}>
    {loading ? 'Sending…' : 'Send'}
  </button>
</form>

use:enhance is just 1 KB and gives you loading states, optimistic UI, and no page flash — all while falling back gracefully without JS.

Named Actions

One page can have multiple actions:

Ctrl+Enter
HTML
CSS
JS
Preview

Live Form with Validation

Ctrl+Enter
HTML
CSS
JS
Preview

Cookies and Sessions

Actions can read and set cookies for session management:

Ctrl+Enter
HTML
CSS
JS
Preview