Runes are special symbols that start with a $ sign. They tell the Svelte compiler to treat certain code specially — usually to make it reactive.
Why Did Svelte Introduce Runes?
In Svelte 4 and earlier, reactivity was "magical". You'd write:
svelte<script> let count = 0; // Svelte 4: This is automatically reactive! </script>
Svelte's compiler would analyze your code and make count reactive behind the scenes. While elegant, this approach had problems:
- Only worked in
.sveltefiles — You couldn't have reactive state in plain.jsfiles - Confusing behavior — Sometimes things weren't reactive when you expected them to be
- Limited TypeScript support — The compiler's magic didn't play well with types
Runes: Explicit is Better
Svelte 5 replaces the magic with explicit Runes. Now you write:
svelte<script> let count = $state(0); // Svelte 5: Explicitly reactive! </script>
The $state() rune clearly marks this variable as reactive. There's no guessing.
The Main Runes
| Rune | Purpose | Example |
|---|---|---|
$state | Create reactive state | let count = $state(0) |
$derived | Computed values | let doubled = $derived(count * 2) |
$effect | Side effects | $effect(() => console.log(count)) |
$props | Component props | let { name } = $props() |
$bindable | Two-way binding | let { value = $bindable() } = $props() |
The Big Win: Universal Reactivity
Runes work everywhere — not just in .svelte files. You can create reactive state in a .js or .ts file (with .svelte.js extension):
js// counter.svelte.js export const counter = $state({ count: 0 }); export function increment() { counter.count += 1; }
This enables powerful patterns for sharing state across your application.