Svelte: The Disappearing Framework

I have been using React for a couple of years now and I genuinely like it. But I keep hearing people talk about Svelte with this particular enthusiasm, so I figured I should see what the excitement is about. After spending two weeks building a small app with it, I understand.
Svelte is not a framework in the traditional sense. React and Vue ship a runtime library to the browser that manages the virtual DOM and reconciliation. Svelte does all of that work at compile time. Your components get compiled into efficient imperative JavaScript that directly manipulates the DOM. The "framework" disappears from the final bundle.
The Component Model
A Svelte component lives in a .svelte file with three sections: script, style, and markup. It looks surprisingly simple.
<script>
let name = 'world';
let count = 0;
function increment() {
count += 1;
}
</script>
<style>
h1 { color: #333; }
button { padding: 8px 16px; }
</style>
<h1>Hello {name}!</h1>
<p>Count: {count}</p>
<button on:click={increment}>
Increment
</button>
Notice there is no useState, no this.setState, no reactive wrapper. You just declare a variable and assign to it. Svelte's compiler detects assignments and generates the DOM update code for you. count += 1 is all it takes to trigger a re-render of the relevant DOM nodes.
Styles are scoped to the component by default. The CSS you write in a Svelte component only applies to that component. No CSS modules, no styled-components, no naming conventions needed.
Reactive Declarations
Svelte has a special syntax for derived values using the $: label.
<script>
let width = 10;
let height = 5;
$: area = width * height;
$: console.log('Area changed:', area);
</script>
<input type="number" bind:value={width} />
<input type="number" bind:value={height} />
<p>Area: {area}</p>
The $: prefix marks a statement as reactive. Whenever width or height changes, area recalculates automatically. The console.log also runs whenever area changes. This is Svelte's equivalent of React's useMemo and useEffect, but with far less ceremony.
The bind:value directive gives you two-way binding with a single attribute. In React, you would need an onChange handler that calls setState. In Svelte, it just works.
Stores for Shared State
For state that needs to be shared across components, Svelte provides stores. A writable store is essentially a reactive value that any component can subscribe to.
// stores.js
import { writable } from 'svelte/store';
export const theme = writable('light');
export const user = writable(null);
<script>
import { theme } from './stores.js';
</script>
<p>Current theme: {$theme}</p>
<button on:click={() => theme.set('dark')}>
Dark Mode
</button>
The $ prefix auto-subscribes to the store and cleans up when the component is destroyed. No provider components, no connect functions, no useContext. You import the store and prefix it with $.
Svelte also has derived stores (computed values from other stores) and readable stores (for values that components can read but not write). The store API is minimal but covers most use cases.
Built-in Transitions
This is one of those features that made me smile. Svelte has transition directives built right into the template syntax.
<script>
import { fade, slide } from 'svelte/transition';
let visible = true;
</script>
{#if visible}
<div transition:fade>This fades in and out</div>
{/if}
{#if visible}
<div in:slide out:fade>Slides in, fades out</div>
{/if}
<button on:click={() => visible = !visible}>
Toggle
</button>
Adding a smooth transition to an element is a single attribute. You can use different transitions for enter and exit, customize duration and easing, and even write custom transition functions. In React, you would reach for a library like Framer Motion or React Transition Group. In Svelte, it is built in.
Bundle Size
Because Svelte compiles away the framework, the bundle size of a Svelte app is significantly smaller than the React equivalent. A minimal React app starts at around 40KB gzipped (React + ReactDOM). A minimal Svelte app can be under 5KB. For larger applications the difference narrows because React's runtime cost is fixed while Svelte's compiled output scales with the number of components, but for small to medium apps the size advantage is meaningful.
SvelteKit
SvelteKit is the official application framework for Svelte, similar to what Next.js is for React. It is still in development (not yet 1.0 at the time of writing), but it provides file-based routing, server-side rendering, API routes, and adapters for different deployment targets. If Svelte is the component layer, SvelteKit is the full-stack layer.
When I Would Choose Svelte
For small to medium applications, Svelte is a joy. The developer experience is the best I have used. Less boilerplate, less configuration, less time fighting the framework. The compiled output is fast and small.
For larger applications or teams, React still has advantages in ecosystem size, hiring pool, and battle-tested patterns for complex state management. The Svelte ecosystem is growing but it is still smaller.
My honest assessment: Svelte makes me wish React worked this way. The compiler approach is elegant, the syntax is clean, and the developer experience is outstanding. I plan to use it for my next personal project. For work projects, I will probably stick with React for now, but I will be keeping a close eye on SvelteKit.