Updated Jul 16, 2026

00 - What are Runes?

📋 Jump to Takeaways

🎁 In Svelte 4 you wrote let count = 0 and it was magically reactive, while $: meant two completely different things depending on the line. What if you could tell exactly what every variable does just by looking at it?

Runes Concept

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, and so on. 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, which is 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 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 Runes Replaced the Old Syntax

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>

The 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 to 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 are 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
  • Runes only work inside .svelte and .svelte.ts/.svelte.js files
  • The next lessons cover each rune in detail

🎁 You now know runes exist and what each one is for. But how does $state actually make the UI update the instant a value changes, and what happens when you put an object or an array inside it?

📝 Ready to test your knowledge?

Answer the quiz below to mark this lesson complete.

Spot something off? Report an issue
© 2026 ByteLearn.dev. Free courses for developers. · Privacy