Svelte 5 Best Practices
Quick Reference
| Topic |
When to Use |
Reference |
| Runes |
$state, $derived, $effect, $props, $bindable, $inspect |
runes.md |
| Snippets |
Replacing slots, {#snippet}, {@render} |
snippets.md |
| Events |
onclick handlers, callback props, context API |
events.md |
| TypeScript |
Props typing, generic components |
typescript.md |
| Migration |
Svelte 4 to 5, stores to runes |
migration.md |
| SvelteKit |
Load functions, form actions, SSR, page typing |
sveltekit.md |
| Performance |
Universal reactivity, avoiding over-reactivity, streaming |
performance.md |
Essential Patterns
Reactive State
<script>
let count = $state(0); // Reactive state
let doubled = $derived(count * 2); // Computed value
</script>
Component Props
<script>
let { name, count = 0 } = $props();
let { value = $bindable() } = $props(); // Two-way binding
</script>
Snippets (replacing slots)
<script>
let { children, header } = $props();
</script>
{@render header?.()}
{@render children()}
Event Handlers
<!-- Svelte 5: use onclick, not on:click -->
<button => count++}>Click</button>
Callback Props (replacing createEventDispatcher)
<script>
let { onclick } = $props();
</script>
<button => onclick?.({ data })}>Click</button>
Common Mistakes
- Using
let without $state - Variables are not reactive without $state()
- Using
$effect for derived values - Use $derived instead
- Using
on:click syntax - Use onclick in Svelte 5
- Using
createEventDispatcher - Use callback props instead
- Using
<slot> - Use snippets with {@render}
- Forgetting
$bindable() - Required for bind: to work
- Setting module-level state in SSR - Causes cross-request leaks
- Sequential awaits in load functions - Use
Promise.all for parallel requests
Source: julien-blanchon/Montelimar — distributed by TomeVault.
1---2name: julien-blanchon-montelimar-montelimar3description: Svelte 5 Best Practices4---56# Svelte 5 Best Practices78## Quick Reference910| Topic | When to Use | Reference |11|-------|-------------|-----------|12| **Runes** | $state, $derived, $effect, $props, $bindable, $inspect | [runes.md](references/runes.md) |13| **Snippets** | Replacing slots, {#snippet}, {@render} | [snippets.md](references/snippets.md) |14| **Events** | onclick handlers, callback props, context API | [events.md](references/events.md) |15| **TypeScript** | Props typing, generic components | [typescript.md](references/typescript.md) |16| **Migration** | Svelte 4 to 5, stores to runes | [migration.md](references/migration.md) |17| **SvelteKit** | Load functions, form actions, SSR, page typing | [sveltekit.md](references/sveltekit.md) |18| **Performance** | Universal reactivity, avoiding over-reactivity, streaming | [performance.md](references/performance.md) |1920## Essential Patterns2122### Reactive State2324```svelte25<script>26 let count = $state(0); // Reactive state27 let doubled = $derived(count * 2); // Computed value28</script>29```3031### Component Props3233```svelte34<script>35 let { name, count = 0 } = $props();36 let { value = $bindable() } = $props(); // Two-way binding37</script>38```3940### Snippets (replacing slots)4142```svelte43<script>44 let { children, header } = $props();45</script>4647{@render header?.()}48{@render children()}49```5051### Event Handlers5253```svelte54<!-- Svelte 5: use onclick, not on:click -->55<button onclick={() => count++}>Click</button>56```5758### Callback Props (replacing createEventDispatcher)5960```svelte61<script>62 let { onclick } = $props();63</script>6465<button onclick={() => onclick?.({ data })}>Click</button>66```6768## Common Mistakes69701. **Using `let` without `$state`** - Variables are not reactive without `$state()`712. **Using `$effect` for derived values** - Use `$derived` instead723. **Using `on:click` syntax** - Use `onclick` in Svelte 5734. **Using `createEventDispatcher`** - Use callback props instead745. **Using `<slot>`** - Use snippets with `{@render}`756. **Forgetting `$bindable()`** - Required for `bind:` to work767. **Setting module-level state in SSR** - Causes cross-request leaks778. **Sequential awaits in load functions** - Use `Promise.all` for parallel requests7879---80> Source: [julien-blanchon/Montelimar](https://github.com/julien-blanchon/Montelimar) — distributed by [TomeVault](https://tomevault.io).81<!-- tomevault:4.0:skill_md:2026-06-25 -->