# Svelte 5 Runes Migration Guide — KoproGo ## Strategy KoproGo migrates from Svelte 5 legacy mode (`export let` + `$:`) to runes (`$props()` + `$state()` + `$derived()` + `$effect()`) **incrementally**. Svelte 5.55 auto-detects runes vs legacy per-component. No global config needed. A component that uses `$props()` is compiled in runes mode; one that uses `export let` stays in legacy mode. Both can coexist in the same project, even as parent-child. ## Migration Pattern (leaf components) Leaf components (no child Svelte components) are the simplest to migrate: ```svelte ``` ### Checklist per component 1. `export let X` → `let { X }: { X: Type } = $props()` 2. `$: Y = expr` → `let Y = $derived(expr)` 3. `$: { sideEffect(); }` → `$effect(() => { sideEffect(); })` 4. `let Z = initialValue` (mutable) → `let Z = $state(initialValue)` 5. Remove `createEventDispatcher` → use callback props 6. Run `npx vitest run ` → must pass 7. Commit ## Parent-Child Interop When a **runes parent** uses a **legacy child** (e.g. ``): - **`on:` directive for component events DOES NOT WORK in runes mode** - Workaround: pass callback props (`onClose`, `onCreated`) instead - This requires the child to accept and call the callback prop - Plan: migrate entire modules at once (all ticket components, then all meeting components) to minimize interop issues When a **legacy parent** uses a **runes child**: - Works seamlessly. The runes child accepts props normally. - `bind:value` from legacy parent to runes child works. ## Known Issues ### vitest + `bind:value` on `` element is mounted in vitest/jsdom. This is because the compiled output references `$state` from the Svelte runtime's index-client.js, and the DEV guard fires in non-.svelte files. **Workaround**: `mode: "production"` in vitest.config.ts (partially helps) or write spec-only tests that don't mount the component. **Tracking**: https://github.com/sveltejs/svelte/issues/12865 ## Progress | Module | Components | Migrated | Tests | |---|---|---|---| | Ticket badges | 2 | 2 ✅ | 11 | | Resolution badges | 1 | 1 ✅ | 3 | | Poll badges | 1 | 1 ✅ | 4 | | Ticket forms/modals | 3 | 0 (needs module-wide migration) | 17 | | Meeting components | 7 | 0 | 5 | | Total | 14 | 4 | 40 |