Progressive enhancement

By using enhance returned from superForm, we’ll get the client-side enhancement expected from a modern website:

<script lang="ts">
  const { form, enhance } = superForm(data.form);
  //            ^^^^^^^

<form method="POST" use:enhance>

The use:enhance action takes no arguments; instead, events are used to hook into the default SvelteKit use:enhance parameters and more. Check out the events page for details.

Modifying the use:enhance behavior

The default use:enhance behavior can be modified, there are three options available, here shown with the default values; you don’t need to add them unless you want to change a value.

const { form, enhance, reset } = superForm(data.form, {
  applyAction: true,
  invalidateAll: true | 'force',
  resetForm: true


When applyAction is true, the form will have the default SvelteKit behavior of both updating and reacting on $page.form and $page.status, and also redirecting automatically.

Turning this behavior off can be useful when you want to isolate the form from other sources updating the page, for example Supabase events, a known source of confusing form behavior. Read more about applyAction in the SvelteKit docs.


When invalidateAll is true (the default) and a successful validation result is returned from the server, the page will be invalidated and the load functions will run again. A login form takes advantage of this to update user information on the page, but the default setting may cause problems with multiple forms on the same page, since the load function will reload the data for all forms defined there.

Optimistic updates

There can be a conflict between the data returned in the form action and the new data from the load function. The form action data is “optimistic”, meaning that what’s returned will be displayed, assuming that all data was supposed to be updated. But if you update the form partially, the form data will be out of sync with the load function data, in which case you may want to wait for the load function data. This can be achieved with by setting invalidateAll: 'force'. Now the load function data will be prioritized, and the reset function will also use the latest load function data when called.


When true, reset the form upon a successful validation result.

Note however, that since we’re using bind:value on the input fields, a HTML form reset (clearing all fields in the DOM) won’t have any effect. So in Superforms, resetting means going back to the initial state of the form data, basically setting $form to what was initially sent to superForm.

For a custom reset, you can instead modify the data field returned from superValidate on the server, or use the events together with the reset function on the client.

When to change the defaults?

Quite rarely! If you have a single form on the page and nothing else is causing the page to invalidate, you’ll probably be fine as it is. For multiple forms on the same page, you have to experiment with these three options. Read more on the multiple forms page.

Making the form behave like the SvelteKit default

Any ActionResult with status error is transformed into failure by Superforms to avoid form data loss. The SvelteKit default is to render the nearest +error.svelte page, which will wipe out the form and all data that was just entered. Returning fail with a status message or using the onError event is a more user-friendly way of handling server errors.

You can prevent this by setting the following option. Use with care, since the purpose of the change is to protect the user from data loss.

const { form, enhance } = superForm(data.form, {
  // On ActionResult error, render the nearest +error.svelte page
  onError: 'apply',