00 - What are Runes?
The Big Idea
Runes are Svelte 5's built-in functions that start with $. They're how you tell Svelte what's reactive, what's computed, what's a side effect, etc. The name "rune" is just Svelte's branding — think of them as special compiler instructions.
They're not regular JavaScript functions — the Svelte compiler transforms them at build time. That's why they only work inside .svelte files (and .svelte.ts files).
All Runes at a Glance
| Rune | Purpose | Lesson |
|---|---|---|
$state() |
Reactive variable — UI updates when it changes | 01 |
$derived() |
Computed value — recalculates when dependencies change | 02 |
$effect() |
Side effect — runs code when dependencies change | 03 |
$props() |
Component inputs — data passed from parent | 04 |
$bindable() |
Two-way binding between parent and child | 05 |
$inspect() |
Debug logging (dev only, removed in production) | 08 |
$host() |
Access host element in web components | 08 |
Why Were Runes Added?
In Svelte 4, reactivity was implicit — the compiler magically made things reactive based on syntax:
<!-- Svelte 4 — implicit, hard to tell what's what -->
<script>
let count = 0; // reactive? yes, but only because it's top-level
$: doubled = count * 2; // computed? side effect? $: was used for both
$: console.log(count); // same $: syntax for a completely different purpose
export let title; // a prop? yes, but looks like a regular export
</script>Problems with this:
- Unclear intent —
$:was used for both computed values AND side effects - Magic behavior — a plain
letbeing reactive isn't obvious to newcomers - Hard to refactor — moving code outside
.sveltefiles broke reactivity - Every
export letwas bindable — no way to opt out
Svelte 5 fixes this with runes — each one has a single, clear purpose:
<!-- Svelte 5 — explicit, each rune has one job -->
<script>
let count = $state(0); // reactive — explicitly opted in
let doubled = $derived(count * 2); // computed — clearly a derived value
$effect(() => console.log(count)); // side effect — clearly a side effect
let { title } = $props(); // prop — clearly an input from parent
</script>Svelte 4 → Svelte 5 Cheat Sheet
| Svelte 4 | Svelte 5 | What it does |
|---|---|---|
let count = 0 |
let count = $state(0) |
Reactive variable |
$: doubled = count * 2 |
let doubled = $derived(count * 2) |
Computed value |
$: { console.log(count) } |
$effect(() => { console.log(count) }) |
Side effect |
export let title |
let { title } = $props() |
Component prop |
export let value + bind:value |
let { value = $bindable() } = $props() |
Two-way binding |
<slot /> |
{@render children()} |
Default content |
<slot name="header" /> |
{@render header()} |
Named content |
on:click={handler} |
onclick={handler} |
Event handler |
Key Takeaways
- Runes = Svelte 5's explicit reactivity system
- Each rune has one clear purpose (no more overloaded
$:) - They replaced Svelte 4's implicit magic with explicit opt-in
- They start with
$and are compiler instructions, not regular functions - The next lessons cover each rune in detail