Sveltekit
-
SvelteKit Forms: Back to Basics (And Why That's a Good Thing)
Before we talk about SvelteKit, we should touch on how React form handling works. I’m writing this to remind myself of the
modernway to do it…- You set up
useStatefor every input field - Write
onChangehandlers to update state on every keystroke - Add an
onSubmithandler to prevent the browser’s default behavior, construct a JSON payload, fire off afetchrequest - Manage loading state to disable the submit button
- Manually parse the response to show success or error messages.
That’s a lot jumps to be hooped.
Frameworks like Next.js have improved this with server actions, but the fundamental approach remains the same: a cage match with the browsers native form handling.
SvelteKit takes a completely different approach. It just uses regular HTML.
How SvelteKit Forms Work
In SvelteKit, you write a standard
<form method="POST">in your+page.sveltefile. That’s your UI. Then, in a+page.server.tsfile in the same directory, you export anactionsobject that handles the submission.The server-side action receives a request object, extracts the form data, runs your logic, and returns either a
redirector afailwith validation errors. No client-side state management, no manual fetch calls, no JSON serialization.// +page.server.ts export const actions = { default: async ({ request }) => { const data = await request.formData(); const email = data.get('email'); const password = data.get('password'); if (!email) { return fail(400, { email, missing: true }); } // authenticate user... throw redirect(303, '/dashboard'); } };If you’re a backend developer coming from Python or Ruby, this should feel familiar. The browser collects the data, posts it to a URL, and the server processes it. Stateless, reliable, and native.
Progressive Enhancement: The Best of Both Worlds
You might be thinking, “Okay, but I don’t want full page reloads every time someone submits a form.” Fair point. SvelteKit handles this with something called progressive enhancement. You add
use:enhanceto your form tag:<form method="POST" use:enhance> <!-- your inputs --> </form>That single directive tells SvelteKit to automatically intercept the submission, prevent the page reload, submit the data via fetch under the hood, and update the
formprop with any validation errors returned from the server.But wait there’s more.
If JavaScript fails to load or the user is on a terrible connection, the form still works. It falls back to the browser’s native POST request.
Your form doesn’t break just because a script didn’t load. That’s how the web is supposed to work.
The React approach treats the browser as a rendering target and reimplements everything in JavaScript. SvelteKit treats the browser as a platform and builds on top of what’s already there.
Now, don’t get me wrong. I’ll write React code any day of the week at the ole w2, but I am really liking how Svelte and SvelteKit has decided to approach these sorts of features.
- You set up
-
Routing in SvelteKit vs Next.js vs Astro
Continuing my series on Svelte, I want to dig into how SvelteKit handles routing and how it compares with Next.js and Astro. These are the frameworks I am most familiar with, so apologies if you wanted a different framework.
Let’s start with everybody’s favorite topic: routing. Okay, maybe I’m the only one excited about this, but stick with me.
Astro: The Traditional Approach
Astro’s routing feels the most traditional of the three. You have a
src/pages/directory, and the file name is the route. Sosrc/pages/dashboard.astromaps to/dashboard. If you’ve worked with PHP or other languages with file-based routing, this will feel immediately familiar.Inside the
.astrofile, you separate your backend logic at the top of the file with---fences. That code runs entirely on the server, and everything below is your HTML template. Clean and straightforward.Next.js: Folder-Based with the App Router
Next.js (the current versions, at least) uses the App Router. The structure is folder-based:
app/dashboard/page.tsxmaps to/dashboard. The key difference from Astro is that the folder name determines the route, but the file must always be calledpage.tsx.By default, everything in the
appdirectory is a server component, meaning it runs on the server. If you want client-side interactivity, you explicitly add"use client"at the top of the file. You can also set"use server"if you want to be explicit, but it’s the default. I think Next.js does a really good job of making it clear what runs where.SvelteKit: Convention Over Configuration
SvelteKit also uses folder-based routing, similar to Next.js. The structure is
src/routes/dashboard/, but instead ofpage.tsx, SvelteKit uses a reserved+prefix for its special files:+page.svelte— Renders on the server, then hydrates on the client+page.server.ts— Runs only on the server (data loading, form actions)+server.ts— A raw API endpoint with no UI
There’s no
"use client"or"use server"directive. The file naming convention itself tells SvelteKit what should run where. If you fetch a database record in+page.server.ts, that data is returned as an object, fully typed, and available in your+page.sveltevia the$propsrune. It just works.The Case for Standard File Names
I can see if some people get annoyed that every route has files named
+page.svelteand+page.server.ts. The files will all look the same in the IDE, but there’s a real advantage here: you can group all related components in the same route folder.For example, if you’re building a dashboard, you can keep your
DashboardChart.svelte,DashboardFilters.svelte, and other components right alongside your+page.svelteand+page.server.ts. You always know which file is the route entry point, which handles server logic, and which are supporting components. It encourages logical grouping instead of scattering related files across the project.Quick Comparison
Feature Astro Next.js SvelteKit Route structure File name = route Folder + page.tsxFolder + +page.svelteServer/client split ---fences"use client"directiveFile naming convention API routes src/pages/api/app/api/route.ts+server.tsDefault rendering Server Server Server + hydration All three frameworks use file-based routing, but they each have a slightly different philosophy about how to organize and separate concerns. Astro keeps it simple with traditional file mapping. Next.js gives you explicit directives. SvelteKit leans on naming conventions to keep things clean.
I think I can get used to the
+prefix convention in SvelteKit. The type safety between your server file and your page component is nice.Next up in the series, I’ll dig into how each framework handles data loading and forms.
/ Astro / svelte / Web development / Sveltekit / Nextjs