Svelte is a JavaScript component framework created by Rich Harris in 2016, notable for its radical philosophical position that the best framework is one that does not exist at runtime. Unlike React and its ilk, which ship a runtime library to the browser and then spend considerable effort pretending the DOM is something other than the DOM, Svelte compiles components into vanilla JavaScript at build time, producing output so clean that the browser has no idea a framework was ever involved.
This is, depending on one’s perspective, either a breakthrough in web development or the logical conclusion of realising that the browser already knows how to update HTML and perhaps we should let it.
Origin
Rich Harris — who had previously created Rollup, a bundler that pioneered tree-shaking (the practice of removing code the application doesn’t use, which in most JavaScript projects constitutes roughly 94% of node_modules) — arrived at Svelte by asking a question that had apparently not occurred to the broader framework community: what if the framework disappeared at build time?
The answer turned out to be: smaller bundles, faster pages, and a reactivity model so intuitive that developers accustomed to React’s useState/useEffect dependency array dance initially suspected a trick.
“The best code is no code. The second-best code is code that deletes itself before the user sees it.”
— The Lizard, reviewing the compiled output
The Compiler Approach
Traditional frameworks ship a runtime to the browser — a reconciliation engine, a virtual DOM differ, a scheduler, an event system — and then your application code runs on top of that machinery. Svelte inverts this entirely. The compiler analyses your components at build time, determines exactly which DOM operations are needed for each state change, and emits precise, surgical JavaScript that does only what is necessary.
There is no virtual DOM. There is no diffing algorithm. There is no reconciliation step. When a variable changes, the compiled code updates exactly the DOM nodes that depend on that variable. Nothing more.
The Lizard has pointed out that this is what printf was doing in 1993, but acknowledges that Svelte at least has the decency to be efficient about it.
Reactivity: The Part That Actually Works
Svelte’s original reactivity model was almost offensively simple. You declared a variable. You assigned to it. The UI updated. That was it.
let count = 0;
function increment() {
count += 1; // the UI updates. that's it. that's the whole thing.
}
The $: reactive declaration let you derive values:
$: doubled = count * 2;
No useState. No useEffect. No dependency arrays that silently break when you forget an entry. No stale closure bugs. No rules of hooks. Just… assignment.
“Wait, that’s it? Where’s the ceremony? Where’s the boilerplate? I haven’t even imported anything yet!”
— The Caffeinated Squirrel, suspicious that something this simple must be hiding a catch
Svelte 5 and the Rune Migration
In 2023, Svelte 5 introduced “runes” — explicit reactivity primitives that replaced the magic $: syntax:
let count = $state(0);
let doubled = $derived(count * 2);
$effect(() => {
console.log(count); // runs when count changes
});
This was simultaneously more verbose and more explicit, which divided the community in the way framework communities are always divided when the syntax they’ve memorised changes. Supporters praised the clarity. Detractors mourned the loss of $:. Both sides wrote blog posts. The compiled output was largely the same.
The Svelte team’s argument was that magic is wonderful until you need to debug it, at which point explicit is better. This is true of both software and stage magic, though the latter has better costumes.
The SvelteKit Question
Here we arrive at the matter that has caused a certain developer genuine, sustained confusion: the boundary between Svelte and SvelteKit.
Svelte is the component framework. It compiles .svelte files into JavaScript. It handles reactivity, templating, transitions, and component composition. This is clear.
SvelteKit is the application framework. It handles routing, server-side rendering, API endpoints, form actions, and deployment. This is also clear.
What is not clear is where one ends and the other begins.
The documentation intermingles them. The tutorials assume SvelteKit. The examples use SvelteKit’s file-based routing. Trying to use “just Svelte” without SvelteKit is technically possible in the way that driving a car without wheels is technically possible — the engine works fine, but you’re not going anywhere useful, and the manual doesn’t cover the procedure because the authors cannot imagine why you’d attempt it.
“Is this a Svelte feature or a SvelteKit feature?”
— a developer, reading the docs for the fourth time“Yes.”
— The documentation
This pattern is not unique to Svelte. React has Next.js. Vue has Nuxt. The framework and the meta-framework merge over time until the original framework becomes, effectively, a compilation target for the meta-framework. The distinction matters architecturally but not practically, because nobody ships the framework alone, because nobody documents how to ship the framework alone, because nobody ships the framework alone.
The developer in question got Svelte working with Go and templ — his server-side HTML templating setup — which required understanding exactly which parts of Svelte could operate independently. This took longer than expected, partly because of the documentation situation and partly because the machine was running slowly that week. Something about Electron processes. Several of them. All claiming to be essential.
The Anti-React
Svelte occupies a specific philosophical position in the JavaScript ecosystem: it is the anti-React.
| Concern | React | Svelte |
|---|---|---|
| Runtime | ~40KB shipped to browser | 0KB (compiled away) |
| DOM updates | Virtual DOM diffing | Direct surgical updates |
| Reactivity | Hooks, dependency arrays, rules | Assignment |
| Bundle size | Large (runtime + reconciler) | Small (only what you use) |
| Learning curve | Steep (hooks rules, closures) | Gentle (it’s just JavaScript) |
| Community size | Enormous | Growing, devoted |
The Lizard approves of the “disappear at build time” philosophy on principle. The best framework is the one that isn’t there at runtime. The best runtime is no runtime. The best abstraction is one that compiles down to what you would have written by hand if you had infinite patience and no social life.
riclib’s Position
A developer keeps Svelte in his back pocket as the answer to “what if HTMX isn’t enough?” For content sites, blogs, and applications where the server sends HTML and the browser renders HTML, HTMX suffices. But when someone asks for a rich, interactive frontend — a complex form, a real-time dashboard, a canvas of draggable elements — Svelte is the strong candidate.
Not React, which ships a runtime and an ideology. Not Vue, which ships a runtime and an apology. Svelte, which ships nothing and lets the browser do its job.
He hasn’t fully committed. He may never fully commit. The Go server renders HTML beautifully, and templ compiles to Go, and the whole stack is pleasingly boring. But if forced to add a frontend framework, Svelte is the one he’d reach for.
Right after he figures out whether he needs SvelteKit for that.
“We could add client-side routing! And transitions! And—”
— The Caffeinated Squirrel, already installing SvelteKit“The component compiled to fourteen lines of JavaScript. Fourteen. I counted.”
— The Lizard, quietly satisfied
Measured Characteristics
| Metric | Value |
|---|---|
| Runtime shipped to browser | 0 KB (by design) |
| Time to understand Svelte | 2 hours |
| Time to understand where Svelte ends and SvelteKit begins | Ongoing |
| Documentation pages that assume SvelteKit | ~87% |
| Reactivity model clarity | Near-perfect (Svelte 4), Explicit (Svelte 5) |
| Community blog posts about the runes migration | 1 per developer per opinion |
| Electron processes running during research for this article | 7 (combined RAM: 4.2 GB) |
| Lines of compiled output per component | Fewer than you’d expect |
| Frameworks created by Rich Harris | At least 2, both excellent |
| Chance riclib fully commits | 62%, pending SvelteKit clarity |
See Also
- React — The framework Svelte defines itself against
- HTMX — For when you don’t need a framework at all
- Next.js — The meta-framework problem, React edition
- Astro — Another compiler-first approach, framework-agnostic
- JavaScript — The language beneath all of this
- The Virtual DOM — The abstraction Svelte refused to use
- The Lizard — Approves of things that disappear
- Go — The server-side language that doesn’t need any of this
