Forms in SvelteKit — Actions, Validation & Progressive Enhancement


Let’s be honest: most apps aren’t impressive because of their fancy buttons or slick layouts. What makes them useful is the stuff you can actually do.

Think about it:

  • A blog without a comment box? That’s just a PDF with nicer fonts.
  • An online store without a checkout form? Nothing more than a digital catalog.
  • A dashboard without settings? Basically a poster that updates itself.

👉 Forms are where your users get to talk back to your app.

Here’s the catch: in many frameworks, building forms feels like busywork. You end up juggling fetch() calls, event listeners, and custom validation code. Miss one tiny detail and your whole flow collapses. Worse, if JavaScript fails (or is disabled), the form stops working entirely.

SvelteKit flips this on its head. Instead of saying “let’s rebuild forms in JavaScript,” it says:

  • Use the HTML forms you already know.
  • They’re accessible by default.
  • They keep working without JavaScript.
  • They handle flaky networks gracefully.

Then, if JavaScript is available, SvelteKit quietly upgrades them with progressive enhancement so they feel as smooth as any SPA form.

That’s the secret sauce: you don’t start fragile and patch on resilience later. You start rock-solid, and only add extra sprinkles when you want them.

In this first part we’ll:

  • Build a contact form that’s 100% HTML.
  • Watch how the browser handles submission all on its own.
  • See how SvelteKit slots into that flow with the special form prop.
  • Call out some easy mistakes beginners make (and how to dodge them).

Later we’ll tackle validation, error handling, redirects, uploads, and even a mini project. But first, let’s pour the foundation.




Step 1 — Create the contact page

Here’s the simplest possible form you can add to a SvelteKit route.

📂 File: src/routes/contact/+page.svelte