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 let being reactive isn't obvious to newcomers
  • Hard to refactor — moving code outside .svelte files broke reactivity
  • Every export let was 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