## docs/svelte/01-introduction/01-overview.md # Overview Svelte compiles declarative components (HTML, CSS, JS) into optimized JavaScript. ## Basic Component ```svelte ``` Use for standalone components or full apps with SvelteKit. **Resources:** [Tutorial](/tutorial) | [Playground](/playground) | [StackBlitz](https://sveltekit.new) ## docs/svelte/01-introduction/02-getting-started.md # Getting started ## Create project ```sh npx sv create myapp cd myapp npm install npm run dev ``` Uses SvelteKit (official framework) + Vite. ## Alternatives - **Vite standalone**: `npm create vite@latest` β†’ select `svelte` option - Generates HTML/JS/CSS in `dist/` - Need to add routing library separately - For SPAs (also possible with SvelteKit) - **Other bundlers**: Plugins available, but Vite recommended ## Editor tooling - [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) - CLI check: `npx sv check` ## Help - [Discord](/chat) - [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte) ## docs/svelte/01-introduction/03-svelte-files.md # .svelte files Components are written in `.svelte` files. All three sections are optional. ```svelte /// file: MyComponent.svelte ``` ## ` ``` Can `export` bindings (becomes module exports). Cannot `export default` (component is default export). > **Note:** Svelte 4 used ` ``` `count` is just a number - update it like any variable. ## Deep state Arrays and plain objects become deeply reactive proxies. Updates trigger granular UI changes. ```js let todos = $state([ { done: false, text: 'add more todos' } ]); // triggers updates for this specific property todos[0].done = !todos[0].done; // new objects are also proxified todos.push({ done: false, text: 'eat lunch' }); ``` **Gotcha:** Destructuring breaks reactivity (values evaluated at destructure time): ```js let { done, text } = todos[0]; // this will NOT affect `done` todos[0].done = !todos[0].done; ``` ## Classes Use `$state` in class fields or first assignment in constructor: ```js class Todo { done = $state(false); constructor(text) { this.text = $state(text); } reset() { this.text = ''; this.done = false; } } ``` **Gotcha:** `this` binding in methods. Use inline function or arrow function: ```svelte ``` Or use arrow function in class: ```js class Todo { done = $state(false); constructor(text) { this.text = $state(text); } reset = () => { this.text = ''; this.done = false; } } ``` **Built-in classes:** Import reactive `Set`, `Map`, `Date`, `URL` from `svelte/reactivity`. ## $state.raw Non-deep reactive state. Can only reassign, not mutate: ```js let person = $state.raw({ name: 'Heraclitus', age: 49 }); // no effect person.age += 1; // works - reassignment person = { name: 'Heraclitus', age: 50 }; ``` Use for performance with large arrays/objects you won't mutate. Raw state can contain reactive state. ## $state.snapshot Takes static snapshot of reactive proxy: ```svelte ``` Useful for external libraries/APIs that don't expect proxies (e.g., `structuredClone`). ## $state.eager Updates UI immediately instead of waiting for `await` synchronization: ```svelte ``` Use sparingly - only for immediate user feedback. ## Passing state into functions JavaScript is pass-by-value. To pass current values, use functions: ```js function add(getA, getB) { return() => getA() + getB(); } let a = 1; let b = 2; let total = add(() => a, () => b); console.log(total()); // 3 a = 3; b = 4; console.log(total()); // 7 ``` Or use getters: ```js function add(input) { return { get value() { return input.a + input.b; } }; } let input = $state({ a: 1, b: 2 }); let total = add(input); console.log(total.value); // 3 input.a = 3; input.b = 4; console.log(total.value); // 7 ``` ## Passing state across modules Can't directly export reassignable state from `.svelte.js`/`.svelte.ts`: ```js // ❌ Won't work export let count = $state(0); ``` **Option 1:** Don't reassign (update properties instead): ```js export const counter = $state({ count: 0 }); export function increment() { counter.count += 1; } ``` **Option 2:** Don't directly export: ```js let count = $state(0); export function getCount() { return count; } export function increment() { count += 1; } ``` ## docs/svelte/02-runes/03-$derived.md # $derived Derived state recalculates when dependencies change: ```svelte

{count} doubled is {doubled}

``` **Rules:** - Expression must be side-effect free (no `count++`) - Can mark class fields as `$derived` - Without `$derived`, values don't update when dependencies change ## `$derived.by` For complex derivations, use `$derived.by` with a function: ```svelte ``` `$derived(expression)` equals `$derived.by(() => expression)` ## Dependencies Anything read synchronously inside `$derived` is a dependency. With `await`, state after the `await` is also tracked: ```js let a = Promise.resolve(1); let b = 2; //cut let total = $derived(await a + b); ``` Both `a` and `b` are tracked. Use `untrack` to exempt state from dependency tracking. ## Overriding Values Derived values can be temporarily reassigned (unless `const`). Useful for optimistic UI: ```svelte ``` ## Deriveds and Reactivity `$derived` values are not deeply reactive (unlike `$state`): ```js // @errors: 7005 let items = $state([ /*...*/ ]); let index = $state(0); let selected = $derived(items[index]); ``` Mutating `selected` affects the underlying `items` array. ## Destructuring Destructured variables are all reactive: ```js function stuff() { return { a: 1, b: 2, c: 3 } } //cut let { a, b, c } = $derived(stuff()); ``` Equivalent to: ```js function stuff() { return { a: 1, b: 2, c: 3 } } //cut let _stuff = $derived(stuff()); let a = $derived(_stuff.a); let b = $derived(_stuff.b); let c = $derived(_stuff.c); ``` ## Update Propagation **Push-pull reactivity:** Dependencies are notified immediately (push), but deriveds only recalculate when read (pull). If a derived's new value is referentially identical to its previous value, downstream updates are skipped: ```svelte ``` Button only updates when `large` changes, not when `count` changes. ## docs/svelte/02-runes/04-$effect.md # $effect Effects run when state updates. Run in browser only, not during SSR. **Don't update state inside effects** - leads to complexity and infinite loops. See alternatives below. ## Basic Usage ```svelte ``` Svelte tracks which state is accessed and re-runs when it changes. ## Lifecycle - Runs after component mounts - Re-runs in microtask after state changes - Re-runs are batched - Can be used anywhere, not just top level ### Teardown Functions ```svelte

{count}

``` ## Dependencies Auto-tracks reactive values (`$state`, `$derived`, `$props`) read **synchronously**. **Async reads not tracked:** ```ts $effect(() => { const context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); // re-runs when `color` changes context.fillStyle = color; setTimeout(() => { // does NOT re-run when `size` changes context.fillRect(0, 0, size, size); }, 0); }); ``` **Object vs property reads:** ```svelte

{state.value} doubled is {derived.value}

``` **Conditional dependencies:** ```ts import confetti from 'canvas-confetti'; let condition = $state(true); let color = $state('#ff3e00'); $effect(() => { if (condition) { confetti({ colors: [color] }); // depends on `condition` and `color` } else { confetti(); // only depends on `condition` } }); ``` Effect only depends on values read in last run. ## `$effect.pre` Runs **before** DOM updates: ```svelte
{#each messages as message}

{message}

{/each}
``` ## `$effect.tracking` Returns `true` if code runs inside tracking context (effect or template): ```svelte

in template: {$effect.tracking()}

``` Used for abstractions like `createSubscriber`. ## `$effect.pending` Returns count of pending promises in current boundary (excludes child boundaries): ```svelte

{a} + {b} = {await add(a, b)}

{#if $effect.pending()}

pending promises: {$effect.pending()}

{/if} ``` ## `$effect.root` Creates non-tracked scope without auto-cleanup. For manual control and effects outside component init: ```js const destroy = $effect.root(() => { $effect(() => { // setup }); return () => { // cleanup }; }); // later... destroy(); ``` ## When NOT to Use ### ❌ Don't synchronize state: ```svelte ``` ### βœ… Use `$derived`: ```svelte ``` For complex logic, use `$derived.by`. Deriveds can be [directly overridden](since 5.25) for optimistic UI. ### ❌ Don't link values with effects: ```svelte ``` ### βœ… Use callbacks or function bindings: ```svelte ``` **If you must update `$state` in effect and hit infinite loop, use `untrack`.** ## docs/svelte/02-runes/05-$props.md # $props Pass props to components like attributes: ```svelte ``` Receive with `$props()` rune (destructuring common): ```svelte

this component is {adjective}

``` ## Fallback values ```js let { adjective = 'happy' } = $props(); ``` > Fallback values are NOT reactive proxies ## Renaming props ```js let { super: trouper = 'lights are gonna find me' } = $props(); ``` ## Rest props ```js let { a, b, c, ...others } = $props(); ``` ## Updating props Props update when parent changes. Child can temporarily **reassign** but should NOT **mutate**. **Reassignment (OK):** ```svelte ``` **Mutation (DON'T):** - Regular object mutation: no effect - Reactive state proxy mutation: works but triggers `ownership_invalid_mutation` warning - Fallback value mutation: no effect Use callback props or [`$bindable`]($bindable) for shared state changes. ## Type safety **TypeScript:** ```svelte ``` **JSDoc:** ```svelte ``` **Interface:** ```svelte ``` Type snippets with `Snippet` from `'svelte'`. Native DOM element interfaces in `svelte/elements`. ## `$props.id()` Generates unique ID per component instance (server/client consistent): ```svelte
``` ## docs/svelte/02-runes/06-$bindable.md # $bindable Props normally flow parent β†’ child. `$bindable` allows two-way binding so data can flow child β†’ parent. Use sparingly. ## Basic Usage **Child component** - mark prop as bindable: ```svelte /// file: FancyInput.svelte ``` **Parent component** - use `bind:` directive: ```svelte /// file: App.svelte

{message}

``` ## Key Points - Parent can pass normal prop without `bind:` - child won't update parent - Allows child to mutate state proxies - Fallback value when no prop passed: ```js /// file: FancyInput.svelte let { value = $bindable('fallback'), ...props } = $props(); ``` > **Warning:** Mutating normal (non-bindable) props triggers warnings. Don't mutate state you don't own. ## docs/svelte/02-runes/07-$inspect.md # $inspect > **Note:** Dev-only. Noop in production. Reactive `console.log` - re-runs when arguments change. Tracks deeply (objects/arrays). ```svelte ``` Prints stack trace on updates (except in playground). ## $inspect(...).with Custom callback instead of `console.log`. First arg is `"init"` or `"update"`, rest are inspected values. ```svelte ``` ## $inspect.trace(...) Traces function re-runs in `$effect` or `$derived`. Shows which reactive state caused re-run. ```svelte ``` Optional first arg for label. ## docs/svelte/02-runes/08-$host.md # $host Provides access to the host element when compiling a component as a custom element. ## Usage ```svelte /// file: Stepper.svelte ``` ```svelte /// file: App.svelte count -= 1} onincrement={() => count += 1} >

count: {count}

``` **Key use case:** Dispatching custom events from custom elements. ## docs/svelte/03-template-syntax/01-basic-markup.md # Basic Markup ## Tags Lowercase tags = HTML elements. Capitalized/dot notation = components. ```svelte
``` ## Element Attributes Attributes work like HTML. Values can contain or be JavaScript expressions. ```svelte page {p} ``` **Boolean attributes:** Included if truthy, excluded if falsy. **Other attributes:** Included unless nullish (`null`/`undefined`). ```svelte
This div has no title attribute
``` **Shorthand:** `{name}` replaces `name={name}`. ```svelte ``` ## Component Props Same rules as attributes. Use shorthand when name matches value. ```svelte ``` ## Spread Attributes Pass multiple attributes/props at once. Order matters for precedence. ```svelte ``` ## Events Event attributes start with `on`. Case sensitive (`onclick` β‰  `onClick`). ```svelte ``` - Shorthand and spread work: ` ``` ```svelte ``` > Avoid props named `children` if component has content inside tags ### Optional snippets ```svelte {@render children?.()} ``` Or with fallback: ```svelte {#if children} {@render children()} {:else} fallback content {/if} ``` ## TypeScript ```svelte ``` With generics: ```svelte ``` ## Exporting Snippets Top-level snippets can be exported from ` {#snippet add(a, b)} {a} + {b} = {a + b} {/snippet} ``` ```svelte {@render add(1, 2)} ``` > Must not reference non-module `
...
``` Multiple attachments per element allowed. ## Attachment factories Functions that return attachments. Re-run when dependencies change: ```svelte ``` ## Inline attachments ```svelte { const context = canvas.getContext('2d'); $effect(() => { context.fillStyle = color; context.fillRect(0, 0, canvas.width, canvas.height); }); }} > ``` Nested effect runs on `color` changes; outer effect runs once. ## Conditional attachments Falsy values = no attachment: ```svelte
...
``` ## With components Attachments on components create Symbol props. Spread props to pass to elements: ```svelte ``` ```svelte ``` ## Controlling re-runs Attachments are fully reactive: `{@attach foo(bar)}` re-runs on changes to `foo`, `bar`, or any state read inside. To prevent expensive re-runs, pass data via function and read in child effect: ```js // @errors: 7006 2304 2552 function foo(getBar) { return (node) => { veryExpensiveSetupWork(node); $effect(() => { update(node, getBar()); }); } } ``` ## Utilities - [`createAttachmentKey`](svelte-attachments#createAttachmentKey): Add attachments to spread objects - [`fromAction`](svelte-attachments#fromAction): Convert actions to attachments ## docs/svelte/03-template-syntax/10-@const.md # {@const ...} **LEGACY:** Use `{const x = $derived(y)}` instead. Defines local constant. Only allowed as immediate child of blocks (`{#if}`, `{#each}`, `{#snippet}`), ``, or ``. ```svelte {#each boxes as box} {@const area = box.width * box.height} {box.width} * {box.height} = {area} {/each} ``` ## docs/svelte/03-template-syntax/11-@debug.md # {@debug ...} Logs variable values when they change and pauses execution in devtools. ```svelte {@debug user}

Hello {user.firstname}!

``` ## Usage **Accepts comma-separated variable names only** (not expressions): ```svelte {@debug user} {@debug user1, user2, user3} ``` **Invalid** (expressions not allowed): ```svelte {@debug user.firstname} {@debug myArray[0]} {@debug !isReady} {@debug typeof user === 'object'} ``` **No arguments** = triggers on any state change: ```svelte {@debug} ``` ## docs/svelte/03-template-syntax/11-declaration-tags.md # {let/const ...} Declaration tags define local variables inside markup: ```svelte {#each boxes as box} {const area = box.width * box.height} {const label = `${box.width} ⨉ ${box.height} = ${area}`}

{label}

{/each} ``` > Available since Svelte 5.56. Replaces legacy `{@const ...}` syntax. ## With Runes Use `$state` and `$derived` for reactive values: ```svelte

Hello {user.name}

{#if editing} {let name = $state(user.name)} {const greeting = $derived(`Hello ${name}`)}

{greeting}

{/if} ``` ## Scoping Declaration tags follow lexical scoping - visible to siblings and their children: ```svelte {const hello = 'hello'} {hello}
{const hello = 'hi'} {hello}
{hello}
{hello} ``` ## docs/svelte/03-template-syntax/12-bind.md # bind: Data flows down (parent β†’ child). `bind:` flows data up (child β†’ parent). Syntax: `bind:property={expression}` or `bind:property` (shorthand when names match) ```svelte ``` Svelte creates event listeners to update bound values. Most bindings are two-way; some are readonly. ## Function bindings Use `bind:property={get, set}` for validation/transformation: ```svelte value, (v) => value = v.toLowerCase()} /> ``` For readonly bindings, set `get` to `null`: ```svelte
...
``` ## `` Binds input's `value` property: ```svelte

{message}

``` Numeric inputs (`type="number"` or `type="range"`) coerce to number: ```svelte

{a} + {b} = {a + b}

``` Empty/invalid value is `undefined`. Since 5.6.0: `defaultValue` reverts on form reset (unless binding is `null`/`undefined`): ```svelte
``` ## `` For checkboxes: ```svelte ``` Since 5.6.0: `defaultChecked` reverts on form reset: ```svelte
``` ## `` For indeterminate checkbox state: ```svelte
{#if indeterminate} waiting... {:else if checked} checked {:else} unchecked {/if}
``` ## `` For radio/checkbox groups: ```svelte

Customize your burrito

Tortilla: {tortilla}

Fillings: {fillings.join(', ') || 'None'}

``` **Note:** Only works if inputs are in same component. ## `` For `type="file"`: ```svelte ``` `FileList` is readonly. Create new `DataTransfer` to modify. ## ` ``` ` ``` Omit `value` if it matches text: ```svelte ``` Use `selected` attribute for default (reverts on form reset): ```svelte ``` ## `