Real Svelte apps are usually SvelteKit apps; it adds routing, server rendering and data loading.
SvelteKit is the application framework for Svelte, built on Vite. Routes are folders in src/routes:
+page.svelterenders a page;src/routes/blog/[slug]/+page.sveltehandles/blog/anything.+layout.sveltewraps child routes; it renders them with{@render children()}.+page.jsor+page.server.jsexports a `load` function that returns data for the page. The page receives it aslet { data } = $props().+page.server.jsruns only on the server, so it can use secrets and databases;+page.jsruns on the server for the first request and in the browser during client-side navigation.+server.jsexportsGET,POSTand other handlers for API endpoints.+error.svelterenders errors thrown witherror(404, 'Not found').
Form actions in +page.server.js handle <form method="POST"> submissions on the server; they work without JavaScript, and use:enhance from $app/forms upgrades them to fetch-based submissions.
Pages are server-rendered by default and then hydrated; after that, navigation happens in the browser, like an SPA. Per route you can set export const prerender = true for static pages or ssr = false for client-only pages.
Adapters produce output for a target: adapter-node, adapter-static, adapter-vercel, adapter-cloudflare and more. adapter-auto detects common platforms.
Example
// src/routes/todos/+page.server.js
import { fail } from '@sveltejs/kit';
import { db } from '$lib/server/db'; // server-only module
export async function load() {
return { todos: await db.todos.all() }; // becomes `data` in the page
}
export const actions = {
default: async ({ request }) => {
const text = (await request.formData()).get('text');
if (!text) return fail(400, { missing: true });
await db.todos.add(String(text));
},
};
// src/routes/todos/+page.svelte
// <script>
// import { enhance } from '$app/forms';
// let { data, form } = $props();
// </script>
// <form method="POST" use:enhance>
// <input name="text" />{#if form?.missing}<p>Required</p>{/if}
// </form>
// {#each data.todos as t (t.id)}<p>{t.text}</p>{/each}Remember
- Routes are folders with
+page.svelte,+layout.svelte,+server.js loadin+page(.server).jsprovidesdata;.serverfiles never reach the browser- Form actions handle POSTs and work without JavaScript;
use:enhanceupgrades them - Adapters target Node, static hosting or serverless platforms
Watch out for
- Importing database code into
+page.js(universal) instead of+page.server.js, exposing it to the browser bundle.