Plain Svelte gives you components; SvelteKit gives you an application — routing, server-side rendering, data loading, and deployment adapters, playing a similar role for Svelte that Next.js plays for React.
SvelteKit is the official application framework built on Svelte, providing file-based routing, server-side rendering with hydration, a load-function pattern for fetching data before rendering, and deployment adapters targeting various hosting platforms. It's the standard choice for building a real, full application with Svelte rather than an embedded component.
Why SvelteKit Matters (and When to Skip It)
Building routing, SSR, and data loading yourself on top of plain Svelte components would mean reimplementing infrastructure that virtually every real application needs — SvelteKit provides this as a cohesive, well-integrated framework, inheriting Svelte's compile-time performance characteristics at the application level.
Skip SvelteKit specifically (while still using Svelte) for a component embedded in a non-Svelte application, or a purely client-side widget where a full application framework's routing and SSR aren't relevant to the use case.
Getting Started with SvelteKit
npx sv create my-app
cd my-app
npm install
npm run dev
File-based routing, with a load function fetching data server-side before render:
src/routes/
+page.svelte
+page.server.ts
products/
[id]/
+page.svelte
+page.server.ts
// src/routes/products/[id]/+page.server.ts
import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async ({ params }) => {
const product = await db.products.findById(params.id);
return { product };
};
<!-- src/routes/products/[id]/+page.svelte -->
<script>
let { data } = $props();
</script>
<h1>{data.product.name}</h1>
Core SvelteKit Concepts Every Developer Should Know
+page.server.ts load functions run only on the server, letting you access databases and secrets directly without exposing them to the client — the server-only naming convention (.server.ts) is enforced at the framework level, preventing accidental exposure.
+page.ts load functions run on both server and client, useful for data fetching that doesn't need server-only resources and should also work during client-side navigation without a full page reload.
Form actions provide a progressive-enhancement-friendly way to handle mutations, working with plain HTML form submissions by default and enhancing to a JavaScript-driven submission when JS is available:
// +page.server.ts
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
await createItem(data.get("name"));
return { success: true };
},
};
Adapters target the specific deployment platform, transforming the SvelteKit build output for the hosting environment (Node.js server, edge/serverless functions, static site) — choosing the right adapter for your deployment target is a required setup step, not an afterthought.
Common SvelteKit Mistakes and How to Fix Them
Mistake 1: putting server-only logic (database calls, secrets) in a +page.ts file instead of +page.server.ts. Since +page.ts runs on the client too, this can expose sensitive logic or fail entirely in the browser. Fix: use .server.ts for anything that must stay server-only.
Mistake 2: not using form actions for mutations, instead building custom client-side fetch logic that loses the progressive enhancement benefit and requires more boilerplate. Fix: use form actions for standard mutation flows, taking advantage of the built-in progressive enhancement.
Mistake 3: choosing the wrong deployment adapter for the target platform, causing build or runtime issues specific to that platform's expectations. Fix: match the adapter explicitly to your actual deployment target rather than assuming a default works everywhere.
When Should You Use SvelteKit Instead of Plain Svelte with a Separate Router?
Use SvelteKit for essentially any real application — its integrated routing, SSR, and load function patterns are well-designed and there's little reason to reassemble that infrastructure manually with plain Svelte and a separate router library. Use plain Svelte components without SvelteKit only when embedding Svelte into a non-Svelte host application or building an isolated widget, where a full application framework isn't the right fit.
SvelteKit in Production
Use the correct adapter for your deployment target from the start, and keep server-only logic properly isolated in .server.ts files as a deliberate security boundary, not just a naming convention to follow loosely. Also take advantage of form actions for mutations where applicable, since the progressive enhancement behavior is a meaningful resilience benefit with little added cost.
If you're building a new Svelte-based application from scratch, defaulting to SvelteKit rather than assembling routing and SSR yourself is close to a strictly better starting point.