## 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{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{message}
{/each}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: ```sveltethis 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.sveltecount: {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