Svelte and SvelteKit course ยท Module 3: Reactivity and Runes

Rune Chamber - Magic of Reactivity

2 min read ยท
In this lesson4

Welcome to the most sacred place in Asgard - the Rune Chamber! Here you will discover the true magic of Svelte: reactivity. In Svelte 5, this magic has taken a new form - the Runes system.

What is Reactivity?

Reactivity is the automatic updating of the interface when data changes. In Svelte it works like runes - once carved, they automatically react to changes.

Svelte 4 vs Svelte 5

Old Magic (Svelte 4)

<!-- Svelte 4 (legacy) -->
<script>
  let count = 0;

  // Reactive declaration - $:
  $: doubled = count * 2;
  $: console.log('Count changed to:', count);
</script>

New Magic - Runes (Svelte 5)

<script>
  let count = $state(0);

  // Derived reactive value
  let doubled = $derived(count * 2);

  // Side effect
  $effect(() => {
    console.log('Count changed to:', count);
  });
</script>

Basic Runes

RuneDescriptionOld Equivalent
$stateReactive statelet x = ...
$derivedDerived value$: x = ...
$effectSide effect$: { ... }
$propsComponent propsexport let
$bindableProp with bindexport let + bind:
$inspectWatching changes in the console (debug)$: console.log(x)

Why Runes?

  1. Explicitness - it is clear what is reactive
  2. TypeScript - better typing
  3. Performance - fine-grained reactivity
  4. Consistency - the same rules everywhere
<script>
  // Svelte 5 with Runes
  let warriors = $state(['Ragnar', 'Bjorn']);
  let count = $derived(warriors.length);

  function addWarrior(name) {
    warriors.push(name); // Works! Runes track mutations
  }
</script>

The runes are carved - the magic is active!

Code for this lesson: App.svelte
<script>
  // Rune Chamber - Magic of Reactivity
  // Svelte 5 Runes: $state, $derived, $effect

  // $state - reactive state
  let count = $state(0);
  let warriors = $state(['Ragnar', 'Bjorn']);

  // $derived - derived value
  let doubled = $derived(count * 2);
  let totalWarriors = $derived(warriors.length);

  // $effect - side effect
  $effect(() => {
    console.log('Count changed to:', count);
  });

  function addWarrior() {
    warriors.push('New Warrior');
  }
</script>

<main class="rune-chamber">
  <h1>Rune Chamber</h1>
  <p class="subtitle">Svelte 5 Runes - A new era of reactivity</p>

  <section class="rune">
    <h2>$state - Reactive state</h2>
    <p>Count: <strong>{count}</strong></p>
    <div class="buttons">
      <button onclick={() => count--}>-</button>
      <button onclick={() => count++}>+</button>
    </div>
  </section>

  <section class="rune">
    <h2>$derived - Derived value</h2>
    <p>Doubled: <strong>{doubled}</strong></p>
    <p class="hint">Automatically = count * 2</p>
  </section>

  <section class="rune">
    <h2>$state with array</h2>
    <p>Warriors ({totalWarriors}):</p>
    <ul>
      {#each warriors as w}
        <li>{w}</li>
      {/each}
    </ul>
    <button onclick={addWarrior}>+ Add warrior</button>
    <p class="hint">In Svelte 5 array mutations work!</p>
  </section>
</main>

<style>
  .rune-chamber {
    font-family: 'Georgia', serif;
    max-width: 600px;
    margin: 0 auto;
    padding: 2rem;
    background: linear-gradient(135deg, #1a0a2e 0%, #2d1b4e 100%);
    color: #e8d5f7;
    min-height: 100vh;
  }

  h1 {
    color: #b19cd9;
    text-align: center;
  }

  .subtitle {
    text-align: center;
    color: #8b7ca8;
  }

  .rune {
    background: rgba(177, 156, 217, 0.1);
    border: 1px solid #b19cd9;
    border-radius: 8px;
    padding: 1.5rem;
    margin: 1rem 0;
  }

  h2 {
    color: #b19cd9;
    margin-top: 0;
    font-size: 1.1rem;
  }

  strong {
    color: #ffd700;
    font-size: 1.5rem;
  }

  .buttons {
    display: flex;
    gap: 0.5rem;
  }

  button {
    padding: 0.5rem 1rem;
    background: #4a2c7a;
    color: white;
    border: 1px solid #b19cd9;
    border-radius: 4px;
    cursor: pointer;
  }

  button:hover {
    background: #5a3c8a;
  }

  ul {
    list-style: none;
    padding: 0;
  }

  li {
    padding: 0.25rem 0.5rem;
    background: rgba(0,0,0,0.3);
    margin: 0.25rem 0;
    border-radius: 4px;
  }

  .hint {
    font-size: 0.85rem;
    color: #8b7ca8;
    font-style: italic;
  }
</style>

Docs entries used in this lesson

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. What are Runes in Svelte 5?

  2. 2. Which Runes are the core ones in Svelte 5?

Useful articles