## docs/svelte/01-introduction/01-overview.md # Svelte Overview Svelte is a UI framework that compiles components into optimized JavaScript. Use it for anything from standalone components to full stack apps with SvelteKit. ```svelte ``` For beginners, start with the [interactive tutorial](/tutorial). Try Svelte online in the [playground](/playground) or on [StackBlitz](https://sveltekit.new). ## docs/svelte/01-introduction/02-getting-started.md # Getting Started with Svelte 5 ## Quick Start ```bash npx sv create myapp cd myapp npm install npm run dev ``` SvelteKit is the recommended framework for most projects. Alternatively: ```bash npm create vite@latest # Select svelte option ``` ## Editor Support - [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) - Command line: `sv check` ## Help Resources - [Discord](/chat) - [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte) ## docs/svelte/01-introduction/03-svelte-files.md # Svelte Components (.svelte files) Components are written in `.svelte` files with three optional sections: ```svelte ``` ## ` ``` You can `export` bindings from this block (except `export default`). ## ` ``` ## docs/svelte/01-introduction/04-svelte-js-files.md # .svelte.js and .svelte.ts files Svelte 5 operates on `.svelte.js` and `.svelte.ts` files in addition to `.svelte` files. These files: - Behave like regular JS/TS modules - Support runes for reactive logic - Allow sharing reactive state across your app ```js // store.svelte.js export let $state count = 0; export const increment = () => count += 1; ``` > Note: You cannot export reassigned state across modules. ## docs/svelte/02-runes/01-what-are-runes.md # Svelte 5 Runes Runes are compiler-controlled symbols in `.svelte` and `.svelte.js`/`.svelte.ts` files with a `$` prefix. ## Key Characteristics - No imports needed - built into Svelte - Not assignable to variables or passable as arguments - Only valid in specific positions (compiler will warn) - Always prefixed with `$` ```js let message = $state('hello'); ``` > Runes are new in Svelte 5 and replace the reactive syntax from previous versions. ## docs/svelte/02-runes/02-$state.md # Svelte 5 Runes - Condensed Documentation ## $state Creates reactive state that triggers UI updates when changed. ```svelte ``` ### Deep state Arrays and objects become deeply reactive state proxies: ```svelte ``` - Modifying nested properties triggers UI updates - New objects added to arrays are automatically proxified - Destructuring breaks reactivity ### Classes Use $state in class fields: ```js class Todo { done = $state(false); text = $state(); constructor(text) { this.text = text; } reset() { this.text = ''; this.done = false; } } ``` When using methods, handle `this` context: ```svelte ``` Or use arrow functions in class: ```js class Todo { // ... reset = () => { this.text = ''; this.done = false; } } ``` ## $state.raw For non-deeply reactive state: ```js let person = $state.raw({ name: 'Heraclitus', age: 49 }); // No effect person.age += 1; // Works - creates new object person = { name: 'Heraclitus', age: 50 }; ``` ## $state.snapshot Create static copy of reactive state: ```svelte ``` ## Passing state State is passed by value, not by reference: ```js let a = $state(1); let b = $state(2); // Accessing current values ``` For reactive objects: ```js function add(input) { return { get value() { return input.a + input.b; } }; } let input = $state({ a: 1, b: 2 }); let total = add(input); ``` ## Cross-module state Can't export directly reassigned state: ```js // Not allowed export let count = $state(0); export function increment() { count += 1; } ``` Instead, export objects: ```js // Allowed - updating property, not reassigning export const counter = $state({ count: 0 }); export function increment() { counter.count += 1; } ``` Or use getter functions: ```js let count = $state(0); export function getCount() { return count; } export function increment() { count += 1; } ``` ## docs/svelte/02-runes/03-$derived.md # $derived Rune in Svelte 5 The `$derived` rune creates reactive values that automatically update when their dependencies change. ## Basic Usage ```svelte

{count} doubled is {doubled}

``` > Without `$derived`, `doubled` would not update when `count` changes. ## Complex Derivations with $derived.by For multi-line derivations, use `$derived.by`: ```svelte ``` `$derived(expression)` is equivalent to `$derived.by(() => expression)`. ## Dependencies Any state read synchronously inside the `$derived` expression becomes a dependency. Use `untrack` to exempt state from being a dependency. ## Overriding Derived Values You can temporarily override derived values by reassigning them (useful for optimistic UI): ```svelte ``` ## Reactivity Behavior Unlike `$state`, `$derived` values are not converted to deeply reactive proxies. When accessing properties of a derived object that references a reactive state, mutations affect the underlying state. ## Update Propagation Svelte uses push-pull reactivity: - Changes are immediately pushed to dependents - Derived values are only recalculated when read - Updates are skipped if the new value is referentially identical to the previous value ```svelte ``` The button text only updates when `large` changes value, not on every `count` change. ## docs/svelte/02-runes/04-$effect.md # Svelte 5 $effect Rune ## Basic Usage Effects run when state updates, useful for third-party libraries, canvas manipulation, or network requests. They only run in the browser. ```svelte ``` ## Lifecycle - Effects run after DOM mounting and in a microtask after state changes - Re-runs are batched and happen after DOM updates - Can return a teardown function that runs before effect re-runs or when destroyed ```svelte

{count}

``` ## Dependencies - Automatically tracks reactive values read synchronously - Async operations (after `await` or in `setTimeout`) won't track dependencies - Only reruns when the object it reads changes, not when properties change - Dependencies are based on what was read in the previous run ```svelte

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

``` ## Variants ### `$effect.pre` Runs before DOM updates: ```svelte
{#each messages as message}

{message}

{/each}
``` ### `$effect.tracking` Tells if code is running in a tracking context: ```svelte

in template: {$effect.tracking()}

``` ### `$effect.root` Creates a non-tracked scope without auto-cleanup: ```js const destroy = $effect.root(() => { $effect(() => { // setup }); return () => { // cleanup }; }); // later... destroy(); ``` ## When Not To Use `$effect` Avoid using for state synchronization. Instead of: ```svelte ``` Use `$derived`: ```svelte ``` For linked values, use function bindings instead of effects: ```svelte ``` ## docs/svelte/02-runes/05-$props.md # $props in Svelte 5 The `$props` rune defines component inputs. ## Basic Usage ```svelte ``` ```svelte

this component is {adjective}

``` ## Fallback Values ```js let { adjective = 'happy' } = $props(); ``` > Note: Fallback values are not reactive state 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 values change. Child components can temporarily override prop values: ```svelte ``` ```svelte ``` ### Important Rules 1. You can reassign props but should not mutate them unless they are `$bindable` 2. Mutating regular objects has no effect 3. Mutating reactive state proxies works but triggers an `ownership_invalid_mutation` warning 4. Fallback values are not reactive state proxies, so mutations won't cause updates ## Type Safety ```svelte ``` Or with JSDoc: ```svelte ``` With separate type declaration: ```svelte ``` ## $props.id() Generates a unique ID for the component instance: ```svelte
``` ## docs/svelte/02-runes/06-$bindable.md # Svelte 5 Condensed: $bindable ## Basic Usage `$bindable` enables two-way data flow between parent and child components. ```svelte /// file: FancyInput.svelte ``` Parent component can bind to the prop: ```svelte /// file: App.svelte

{message}

``` ## Default Values Provide fallback values when no prop is passed: ```js /// file: FancyInput.svelte let { value = $bindable('fallback'), ...props } = $props(); ``` ## Key Points - Props normally flow one-way (parent to child) - `$bindable` allows data to flow up from child to parent - Parent components can choose whether to use `bind:` or not - Use sparingly to maintain clear data flow in your app - State proxies can be mutated in child components ## docs/svelte/02-runes/07-$inspect.md # Svelte 5 Documentation: $inspect ## Basic Usage ```svelte ``` > **Note**: `$inspect` only works during development. In production, it becomes a no-op. ## $inspect(...).with Customize logging behavior with a callback: ```svelte ``` Quick trace shorthand: ```js $inspect(stuff).with(console.trace); ``` ## $inspect.trace(...) Traces reactive dependencies in development: ```svelte ``` Accepts an optional label parameter. ## docs/svelte/02-runes/08-$host.md # $host When compiling a component as a custom element, the `$host` rune provides access to the host element. ```svelte /// file: Stepper.svelte ``` ```svelte /// file: App.svelte count -= 1} onincrement={() => count += 1} >

count: {count}

``` ## docs/svelte/03-template-syntax/01-basic-markup.md # Basic Markup in Svelte 5 ## Tags ```svelte
``` - Lowercase tags (`
`) = HTML elements - Capitalized tags or dot notation (``, ``) = components ## Element Attributes ```svelte
page {p}
This div has no title attribute
``` ## Component Props ```svelte ``` ## Events ```svelte ``` - Event attributes are case sensitive (`onclick` โ‰  `onClick`) - Can use shorthand: `` - Can spread events: `` - `ontouchstart` and `ontouchmove` are passive by default ### Event Delegation Svelte uses event delegation for performance. Important notes: - When manually dispatching events, use `{ bubbles: true }` - Avoid `stopPropagation` with `addEventListener` - Use `on` from `svelte/events` instead of `addEventListener` Delegated events: `beforeinput`, `click`, `change`, `dblclick`, `contextmenu`, `focusin`, `focusout`, `input`, `keydown`, `keyup`, `mousedown`, `mousemove`, `mouseout`, `mouseover`, `mouseup`, `pointerdown`, `pointermove`, `pointerout`, `pointerover`, `pointerup`, `touchend`, `touchmove`, `touchstart` ## Text Expressions ```svelte

Hello {name}!

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

{(/^[A-Za-z ]+$/).test(value) ? x : y}
{@html potentiallyUnsafeHtmlString} ``` - `null` or `undefined` expressions are omitted - All others are coerced to strings - Escape curly braces with HTML entities: `{`, `{`, `{`, `}`, `}`, `}` ## Comments ```svelte

Hello world

Hello, {name}

``` - Use `` to disable warnings - Use `` for component documentation ## docs/svelte/03-template-syntax/02-if.md # {#if ...} ```svelte {#if expression}...{/if} {#if expression}...{:else if expression}...{/if} {#if expression}...{:else}...{/if} ``` Conditionally render content with if blocks: ```svelte {#if answer === 42}

what was the question?

{/if} ``` Chain conditions with `:else if` and `:else`: ```svelte {#if porridge.temperature > 100}

too hot!

{:else if 80 > porridge.temperature}

too cold!

{:else}

just right!

{/if} ``` Note: Blocks can wrap elements or text within elements. ## docs/svelte/03-template-syntax/03-each.md # Svelte 5 Each Blocks ## Basic Usage ```svelte {#each expression as name}...{/each} {#each expression as name, index}...{/each} ``` Iterate over arrays, array-likes, or iterables (Map, Set, etc.): ```svelte

Shopping list

    {#each items as item}
  • {item.name} x {item.qty}
  • {/each}
``` With index: ```svelte {#each items as item, i}
  • {i + 1}: {item.name} x {item.qty}
  • {/each} ``` ## Keyed Each Blocks ```svelte {#each expression as name (key)}...{/each} {#each expression as name, index (key)}...{/each} ``` Keys help Svelte efficiently update lists when data changes: ```svelte {#each items as item (item.id)}
  • {item.name} x {item.qty}
  • {/each} {#each items as item, i (item.id)}
  • {i + 1}: {item.name} x {item.qty}
  • {/each} ``` ## Destructuring ```svelte {#each items as { id, name, qty }, i (id)}
  • {i + 1}: {name} x {qty}
  • {/each} {#each objects as { id, ...rest }}
  • {id}
  • {/each} {#each items as [id, ...rest]}
  • {id}
  • {/each} ``` ## Each Without Item For repeating n times: ```svelte {#each { length: 8 }, rank} {#each { length: 8 }, file}
    {/each} {/each} ``` ## Else Blocks ```svelte {#each todos as todo}

    {todo.text}

    {:else}

    No tasks today!

    {/each} ``` ## docs/svelte/03-template-syntax/04-key.md # {#key ...} ```svelte {#key expression}...{/key} ``` Key blocks destroy and recreate their contents when an expression value changes: ```svelte {#key value} {/key} ``` Useful for: - Reinstantiating components when a value changes - Triggering transitions on value changes: ```svelte {#key value}
    {value}
    {/key} ``` ## docs/svelte/03-template-syntax/05-await.md # {#await ...} ```svelte {#await expression}...{:then name}...{:catch name}...{/await} {#await expression}...{:then name}...{/await} {#await expression then name}...{/await} {#await expression catch name}...{/await} ``` Await blocks handle the three states of a Promise: ```svelte {#await promise}

    waiting for the promise to resolve...

    {:then value}

    The value is {value}

    {:catch error}

    Something went wrong: {error.message}

    {/await} ``` > During SSR, only the pending branch renders. Non-Promise expressions only render the `:then` branch. **Simplified variants:** ```svelte {#await promise}

    waiting for the promise to resolve...

    {:then value}

    The value is {value}

    {/await} ``` ```svelte {#await promise then value}

    The value is {value}

    {/await} ``` ```svelte {#await promise catch error}

    The error is {error}

    {/await} ``` > Use with dynamic imports for lazy loading: > ```svelte > {#await import('./Component.svelte') then { default: Component }} > > {/await} > ``` ## docs/svelte/03-template-syntax/06-snippet.md # Svelte 5 Snippets ## {#snippet ...} ```svelte {#snippet name()}...{/snippet} {#snippet name(param1, param2, paramN)}...{/snippet} ``` Snippets create reusable markup chunks within components: ```svelte {#snippet figure(image)}
    {image.caption}
    {image.caption}
    {/snippet} {#each images as image} {#if image.href} {@render figure(image)} {:else} {@render figure(image)} {/if} {/each} ``` Snippets can have parameters with default values and destructuring (no rest parameters). ## Scope Snippets can access outer scope values: ```svelte {#snippet hello(name)}

    hello {name}! {message}!

    {/snippet} {@render hello('alice')} {@render hello('bob')} ``` Snippets are visible to siblings and their children. They can reference themselves and other snippets: ```svelte {#snippet countdown(n)} {#if n > 0} {n}... {@render countdown(n - 1)} {:else} {@render blastoff()} {/if} {/snippet} {#snippet blastoff()} ๐Ÿš€ {/snippet} {@render countdown(10)} ``` ## Passing Snippets to Components ### Explicit Props ```svelte {#snippet header()} fruit qty price total {/snippet} {#snippet row(d)} {d.name} {d.qty} {d.price} {d.qty * d.price} {/snippet} ``` ### Implicit Props Snippets declared inside a component become props on the component: ```svelte
    {#snippet header()} {/snippet} {#snippet row(d)} {/snippet}
    fruit qty price total{d.name} {d.qty} {d.price} {d.qty * d.price}
    ``` ### Implicit `children` Snippet Non-snippet content becomes the `children` snippet: ```svelte ``` ```svelte ``` > Don't create a prop named `children` if you also have content inside the component ### Optional Snippet Props Handle optional snippets with optional chaining: ```svelte {@render children?.()} ``` Or with fallback content: ```svelte {#if children} {@render children()} {:else} fallback content {/if} ``` ## Typing Snippets ```svelte ``` ## Exporting Snippets Top-level snippets can be exported from ` {#snippet add(a, b)} {a} + {b} = {a + b} {/snippet} ``` > Requires Svelte 5.5.0+ ## Advanced Usage - Programmatic snippets can be created with `createRawSnippet` API - Snippets replace slots in Svelte 5 (slots are deprecated) ## docs/svelte/03-template-syntax/07-@render.md # {@render ...} Use `{@render ...}` to render [snippets](snippet). ```svelte {#snippet sum(a, b)}

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

    {/snippet} {@render sum(1, 2)} {@render sum(3, 4)} {@render sum(5, 6)} ``` The expression can be an identifier or any JavaScript expression: ```svelte {@render (cool ? coolSnippet : lameSnippet)()} ``` ## Optional snippets For potentially undefined snippets, use optional chaining: ```svelte {@render children?.()} ``` Or use an `{#if ...}` block with fallback content: ```svelte {#if children} {@render children()} {:else}

    fallback content

    {/if} ``` ## docs/svelte/03-template-syntax/08-@html.md # {@html ...} Use `{@html ...}` to inject raw HTML into your component: ```svelte
    {@html content}
    ``` > [!NOTE] Always sanitize HTML content to prevent XSS attacks. ## Limitations - Expression must be valid standalone HTML - Will not compile Svelte code - Cannot split HTML tags across multiple `{@html}` tags ## Styling Content rendered with `{@html ...}` is invisible to Svelte's style scoping: ```svelte ``` ## docs/svelte/03-template-syntax/09-@const.md # {@const ...} The `{@const ...}` tag defines a local constant within a block. ```svelte {#each boxes as box} {@const area = box.width * box.height} {box.width} * {box.height} = {area} {/each} ``` Only allowed as an immediate child of: - Blocks (`{#if ...}`, `{#each ...}`, `{#snippet ...}`, etc.) - Components (``) - `` ## docs/svelte/03-template-syntax/10-@debug.md # {@debug ...} The `{@debug ...}` tag provides debugging capabilities in Svelte components: ```svelte {@debug user}

    Hello {user.firstname}!

    ``` ## Usage - Logs values when they change and pauses execution if devtools are open - Accepts comma-separated variable names (not expressions): ```svelte {@debug user} {@debug user1, user2, user3} ``` - Without arguments, triggers on any state change: ```svelte {@debug} ``` ## docs/svelte/03-template-syntax/11-bind.md # Svelte 5 and SvelteKit Condensed Documentation ## bind: Data flows down from parent to child. `bind:` allows data to flow upward. ```svelte ``` ### Function bindings (v5.9.0+) ```svelte value, (v) => value = v.toLowerCase()} />
    ...
    ``` ### Input bindings ```svelte ``` ### Select bindings ```svelte ``` ### Media element bindings ```svelte ``` ### Other element bindings ```svelte
    Title

    Content

    ``` ### bind:this ```svelte ``` ### Component bindings ```svelte ``` ## docs/svelte/03-template-syntax/12-use.md # use: Directive in Svelte 5 Actions are functions called when an element is mounted, added with the `use:` directive. ## Basic Usage ```svelte
    ...
    ``` ## With Parameters ```svelte
    ...
    ``` > Note: Actions run once when mounted (not during SSR). They don't re-run if parameters change. ## Typing ```svelte
    ...
    ``` The `Action` interface accepts three optional type arguments: 1. Node type (can be `Element` for all elements) 2. Parameter type 3. Custom event handlers created by the action ## docs/svelte/03-template-syntax/13-transition.md # Svelte 5 Transitions ## Basic Usage Transitions are triggered when elements enter or leave the DOM due to state changes. ```svelte {#if visible}
    fades in and out
    {/if} ``` ## Local vs Global Transitions are local by default - they only play when their immediate block is created/destroyed. ```svelte {#if x} {#if y}

    fades in and out only when y changes

    fades in and out when x or y change

    {/if} {/if} ``` ## Parameters ```svelte {#if visible}
    fades in and out over two seconds
    {/if} ``` ## Custom Transitions ```js transition = (node: HTMLElement, params: any, options: { direction: 'in' | 'out' | 'both' }) => { delay?: number, duration?: number, easing?: (t: number) => number, css?: (t: number, u: number) => string, tick?: (t: number, u: number) => void } ``` CSS-based custom transition (preferred for performance): ```svelte {#if visible}
    whooshes in
    {/if} ``` JavaScript-based custom transition (use `css` when possible): ```svelte {#if visible}

    The quick brown fox jumps over the lazy dog

    {/if} ``` ## Transition Events Elements with transitions dispatch these events: - `introstart` - `introend` - `outrostart` - `outroend` ```svelte {#if visible}

    (status = 'intro started')} onoutrostart={() => (status = 'outro started')} onintroend={() => (status = 'intro ended')} onoutroend={() => (status = 'outro ended')} > Flies in and out

    {/if} ``` ## docs/svelte/03-template-syntax/14-in-and-out.md # in: and out: Directives These directives create one-way transitions that don't reverse when interrupted. ```svelte {#if visible}
    flies in, fades out
    {/if} ``` Key differences from `transition:`: - Transitions are not bidirectional - An `in` transition continues playing alongside the `out` transition - If an `out` transition is aborted, transitions restart from scratch ## docs/svelte/03-template-syntax/15-animate.md # animate: Animations trigger when contents of a keyed each block are re-ordered (not when elements are added/removed). ```svelte {#each list as item, index (item)}
  • {item}
  • {/each} ``` ## Animation Parameters ```svelte {#each list as item, index (item)}
  • {item}
  • {/each} ``` ## Custom animation functions ```js animation = (node: HTMLElement, { from: DOMRect, to: DOMRect }, params: any) => { delay?: number, duration?: number, easing?: (t: number) => number, css?: (t: number, u: number) => string, tick?: (t: number, u: number) => void } ``` Custom animations receive: - `node`: The HTML element - `animation`: Object with `from` and `to` DOMRect properties - `parameters`: Any custom parameters Return an object with either: - `css` method (preferred, runs off main thread) - `tick` function (runs during animation) ```svelte {#each list as item, index (item)}
    {item}
    {/each} ``` Using `tick` instead of `css`: ```svelte {#each list as item, index (item)}
    {item}
    {/each} ``` > Prefer `css` over `tick` for better performance on slower devices. ## docs/svelte/03-template-syntax/17-style.md # style: directive The `style:` directive provides a shorthand for setting styles on elements. ## Basic Usage ```svelte
    ...
    ...
    ``` ## Dynamic Values ```svelte
    ...
    ``` ## Shorthand Form ```svelte
    ...
    ``` ## Multiple Styles ```svelte
    ...
    ``` ## Important Modifier ```svelte
    ...
    ``` ## Precedence When combined with `style` attributes, directives take precedence: ```svelte
    This will be red
    ``` ## docs/svelte/03-template-syntax/18-class.md # Svelte Class Handling ## Class Attribute ### Basic Usage ```svelte
    ...
    ``` > Note: Falsy values are stringified, but `undefined`/`null` omit the attribute entirely. ### Objects and Arrays (Svelte 5.16+) **Objects** - truthy keys are added: ```svelte
    ...
    ``` **Arrays** - truthy values are combined: ```svelte
    ...
    ``` **Combining with props**: ```svelte ``` Usage: ```svelte ``` ### TypeScript Support ```svelte
    ...
    ``` ## Class Directive (Legacy) ```svelte
    ...
    ``` Shorthand when name matches value: ```svelte
    ...
    ``` > Note: Prefer using the class attribute with objects/arrays over class: directives in Svelte 5.16+. ## docs/svelte/04-styling/01-scoped-styles.md # Scoped Styles in Svelte ## Basic Scoping Styles in ` ``` ## Specificity - Scoped selectors get a specificity boost of 0-1-0 from the added class - Component styles override global styles with the same selector, even if loaded later - Multiple occurrences of the scoping class after the first use `:where(.svelte-xyz123)` to avoid further specificity increases ## Scoped Keyframes Keyframe animations are also scoped to the component: ```svelte ``` ## docs/svelte/04-styling/02-global-styles.md # Global Styles in Svelte ## :global(...) Apply styles globally to specific selectors: ```svelte ``` For global keyframes, prepend names with `-global-`: ```svelte ``` ## :global Apply styles to multiple selectors globally using a block: ```svelte ``` ## docs/svelte/04-styling/03-custom-properties.md # Custom Properties Pass CSS custom properties to components: ```svelte ``` This desugars to: ```svelte ``` For SVG elements, it uses `` instead: ```svelte ``` Inside components, access these properties with fallbacks: ```svelte ``` Custom properties can also be defined on parent elements (like `:root`) to apply globally. > Note: The wrapper element won't affect layout but may impact CSS selectors using the `>` combinator. ## docs/svelte/04-styling/04-nested-style-elements.md # Nested `
    ``` ## docs/svelte/05-special-elements/01-svelte-boundary.md # Svelte 5 Error Boundaries ## `` ```svelte ... ``` Error boundaries isolate errors in components to prevent app-wide crashes and enable recovery. - Catches errors during rendering, updating, and `$effect` execution - Does NOT catch errors in event handlers, timeouts, or async operations ## Properties ### `failed` Renders fallback UI with error details and reset function: ```svelte {#snippet failed(error, reset)} {/snippet} ``` ### `onerror` Handles errors programmatically: ```svelte report(e)}> ... ``` Managing error state outside the boundary: ```svelte {#if error} {/if} ``` Errors in `onerror` propagate to parent boundaries. ## docs/svelte/05-special-elements/02-svelte-window.md # Svelte Window Element ## `` Adds event listeners to the `window` object without manual cleanup. ```svelte ``` Must appear at the top level of your component. ### Event Example ```svelte ``` ### Bindable Properties ```svelte ``` **Read/Write Properties:** - `scrollX` - `scrollY` **Readonly Properties:** - `innerWidth` - `innerHeight` - `outerWidth` - `outerHeight` - `online` (alias for `window.navigator.onLine`) - `devicePixelRatio` > **Note:** Page won't scroll to initial bound values of `scrollX`/`scrollY`. For initial scrolling, use `scrollTo()` in an `$effect`. ## docs/svelte/05-special-elements/03-svelte-document.md # ```svelte ``` Allows adding event listeners and actions to the `document` object. - Must appear only at the top level of your component - Never place inside blocks or elements - Useful for events that don't fire on `window` (e.g., `visibilitychange`) ```svelte ``` ## Bindable Properties (readonly) - `activeElement` - `fullscreenElement` - `pointerLockElement` - `visibilityState` ## docs/svelte/05-special-elements/04-svelte-body.md # ```svelte ``` Allows adding event listeners to `document.body` for events that don't fire on `window` (like `mouseenter`/`mouseleave`). Also supports [actions](use). **Rules:** - Must appear only at top level of component - Cannot be inside blocks or elements **Example:** ```svelte ``` ## docs/svelte/05-special-elements/05-svelte-head.md # ```svelte ... ``` Inserts elements into `document.head`. During SSR, head content is exposed separately from body content. **Rules:** - Must appear only at top level of component - Cannot be inside blocks or elements **Example:** ```svelte Hello world! ``` ## docs/svelte/05-special-elements/06-svelte-element.md # ```svelte ``` Renders an element that's unknown at author time (e.g., from a CMS). ## Usage ```svelte Content inside the dynamic element ``` ## Key Points - Only `bind:this` binding is supported - If `this` is nullish, nothing renders - If `this` is a void element (e.g., `br`) with children, a runtime error occurs in dev mode ```svelte This text cannot appear inside an hr element ``` - Specify namespace explicitly when needed: ```svelte ``` - `this` must be a valid DOM element tag (`#text` or `svelte:head` won't work) ## docs/svelte/05-special-elements/07-svelte-options.md # `` ```svelte ``` ## Available Options - `runes={true|false}` - Forces component into runes or legacy mode - `namespace="html|svg|mathml"` - Sets component namespace (default: "html") - `customElement={...}` - Options for custom element compilation - `css="injected"` - Injects styles inline ```svelte ``` > Note: `immutable`, `accessors` options are deprecated in Svelte 5 and non-functional in runes mode. ## docs/svelte/06-runtime/01-stores.md # Svelte Stores ## Overview A store is an object that allows reactive access to a value via a store contract. Access store values in components with the `$` prefix. ```svelte ``` ## When to Use Stores In Svelte 5, runes are preferred for most use cases: ```ts /// file: state.svelte.js export const userState = $state({ name: 'name', /* ... */ }); ``` ```svelte

    User name: {userState.name}

    ``` Use stores for complex async data streams or when manual control over updates is needed. ## svelte/store API ### `writable` Creates a store with values that can be set externally. ```js import { writable } from 'svelte/store'; const count = writable(0); count.subscribe((value) => { console.log(value); }); // logs '0' count.set(1); // logs '1' count.update((n) => n + 1); // logs '2' ``` With start/stop functions: ```js import { writable } from 'svelte/store'; const count = writable(0, () => { console.log('got a subscriber'); return () => console.log('no more subscribers'); }); count.set(1); // does nothing const unsubscribe = count.subscribe((value) => { console.log(value); }); // logs 'got a subscriber', then '1' unsubscribe(); // logs 'no more subscribers' ``` ### `readable` Creates a store whose value cannot be set externally. ```ts import { readable } from 'svelte/store'; const time = readable(new Date(), (set) => { set(new Date()); const interval = setInterval(() => { set(new Date()); }, 1000); return () => clearInterval(interval); }); const ticktock = readable('tick', (set, update) => { const interval = setInterval(() => { update((sound) => (sound === 'tick' ? 'tock' : 'tick')); }, 1000); return () => clearInterval(interval); }); ``` ### `derived` Derives a store from one or more other stores. ```ts import { derived } from 'svelte/store'; const doubled = derived(a, ($a) => $a * 2); ``` Asynchronous derivation: ```ts import { derived } from 'svelte/store'; const delayed = derived( a, ($a, set) => { setTimeout(() => set($a), 1000); }, 2000 ); const delayedIncrement = derived(a, ($a, set, update) => { set($a); setTimeout(() => update((x) => x + 1), 1000); }); ``` With cleanup function: ```ts import { derived } from 'svelte/store'; const tick = derived( frequency, ($frequency, set) => { const interval = setInterval(() => { set(Date.now()); }, 1000 / $frequency); return () => { clearInterval(interval); }; }, 2000 ); ``` Multiple source stores: ```ts import { derived } from 'svelte/store'; const summed = derived([a, b], ([$a, $b]) => $a + $b); const delayed = derived([a, b], ([$a, $b], set) => { setTimeout(() => set($a + $b), 1000); }); ``` ### `readonly` Makes a store readonly. ```js import { readonly, writable } from 'svelte/store'; const writableStore = writable(1); const readableStore = readonly(writableStore); readableStore.subscribe(console.log); writableStore.set(2); // console: 2 // readableStore.set(2); // ERROR ``` ### `get` Retrieves the current value of a store without subscribing. ```ts import { get } from 'svelte/store'; const value = get(store); ``` ## Store Contract A valid store must: 1. Have a `.subscribe` method that accepts a subscription function 2. Call the subscription function immediately with the current value 3. Return an unsubscribe function 4. Optionally have a `.set` method (for writable stores) ## docs/svelte/06-runtime/02-context.md # Context Context allows components to access values from parent components without prop-drilling. ## Basic Usage ```svelte ``` ```svelte

    {message}, inside Child.svelte

    ``` Usage: ```svelte ``` Available functions: `setContext`, `getContext`, `hasContext`, `getAllContexts` ## Context with State ```svelte ``` โš ๏ธ Update properties directly rather than reassigning the object: ```svelte ``` ## Type-safe Context ```js /// file: context.js // @filename: ambient.d.ts interface User {} // @filename: index.js import { getContext, setContext } from 'svelte'; const key = {}; /** @param {User} user */ export function setUserContext(user) { setContext(key, user); } export function getUserContext() { return /** @type {User} */ (getContext(key)); } ``` ## Alternative to Global State Context is safer than global state for server-side rendering, as it's not shared between requests. ```js /// file: state.svelte.js export const myGlobalState = $state({ user: { // ... } // ... }); ``` Using global state during SSR can leak data between users: ```svelte ``` ## docs/svelte/06-runtime/03-lifecycle-hooks.md # Svelte 5 Lifecycle Hooks ## Component Lifecycle In Svelte 5, components have only two lifecycle phases: - Creation (mounting) - Destruction (unmounting) State updates trigger only the specific effects that depend on that state. ## `onMount` Runs after component is mounted to DOM. Not executed during SSR. ```svelte ``` > [!NOTE] Cleanup only works when function synchronously returns a value (not with async functions). ## `onDestroy` Runs before component unmounts. Only lifecycle hook that runs during SSR. ```svelte ``` ## `tick` Returns promise that resolves after pending state changes are applied. ```svelte ``` ## Deprecated: `beforeUpdate` / `afterUpdate` Shimmed for backward compatibility but not available in components using runes. - Use `$effect.pre` instead of `beforeUpdate` - Use `$effect` instead of `afterUpdate` ### Chat Window Example ```svelte
    {#each messages as message}

    {message}

    {/each}
    ``` ## docs/svelte/06-runtime/04-imperative-component-api.md # Imperative Component API ## `mount` Creates and mounts a component to a target element: ```js import { mount } from 'svelte'; import App from './App.svelte'; const app = mount(App, { target: document.querySelector('#app'), props: { some: 'property' } }); ``` **Note**: Effects (including `onMount` callbacks and action functions) don't run during `mount`. Use `flushSync()` to force pending effects to run. ## `unmount` Removes a previously mounted component: ```js import { mount, unmount } from 'svelte'; import App from './App.svelte'; const app = mount(App, { target: document.body }); // later unmount(app, { outro: true }); ``` Returns a `Promise` that resolves after transitions complete (if `outro: true`) or immediately otherwise. ## `render` Server-side only. Returns HTML for server rendering: ```js import { render } from 'svelte/server'; import App from './App.svelte'; const result = render(App, { props: { some: 'property' } }); result.body; // HTML for result.head; // HTML for ``` ## `hydrate` Reuses SSR-rendered HTML and makes it interactive: ```js import { hydrate } from 'svelte'; import App from './App.svelte'; const app = hydrate(App, { target: document.querySelector('#app'), props: { some: 'property' } }); ``` Like `mount`, effects don't run during `hydrate` - use `flushSync()` afterward if needed. ## docs/svelte/07-misc/02-testing.md # Svelte Testing Guide ## Unit and Integration Testing with Vitest ### Setup ```bash npm install -D vitest ``` Configure Vite: ```js // vite.config.js import { defineConfig } from'vitest/config'; export default defineConfig({ // Tell Vitest to use browser entry points resolve: process.env.VITEST ? { conditions: ['browser'] } : undefined }); ``` ### Testing JavaScript Functions ```js // multiplier.svelte.test.js import { flushSync } from 'svelte'; import { expect, test } from 'vitest'; import { multiplier } from './multiplier.svelte.js'; test('Multiplier', () => { let double = multiplier(0, 2); expect(double.value).toEqual(0); double.set(5); expect(double.value).toEqual(10); }); ``` ### Using Runes in Tests Filename must include `.svelte`: ```js // multiplier.svelte.test.js import { flushSync } from 'svelte'; import { expect, test } from 'vitest'; import { multiplier } from './multiplier.svelte.js'; test('Multiplier', () => { let count = $state(0); let double = multiplier(() => count, 2); expect(double.value).toEqual(0); count = 5; expect(double.value).toEqual(10); }); ``` ### Testing Effects Wrap in `$effect.root` and use `flushSync()`: ```js // logger.svelte.test.js import { flushSync } from 'svelte'; import { expect, test } from 'vitest'; import { logger } from './logger.svelte.js'; test('Effect', () => { const cleanup = $effect.root(() => { let count = $state(0); let log = logger(() => count); flushSync(); expect(log.value).toEqual([0]); count = 1; flushSync(); expect(log.value).toEqual([0, 1]); }); cleanup(); }); ``` ## Component Testing ### Setup ```bash npm install -D jsdom ``` Update Vite config: ```js // vite.config.js import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { environment: 'jsdom' }, resolve: process.env.VITEST ? { conditions: ['browser'] } : undefined }); ``` ### Basic Component Test ```js // component.test.js import { flushSync, mount, unmount } from 'svelte'; import { expect, test } from 'vitest'; import Component from './Component.svelte'; test('Component', () => { const component = mount(Component, { target: document.body, props: { initial: 0 } }); expect(document.body.innerHTML).toBe(''); document.body.querySelector('button').click(); flushSync(); expect(document.body.innerHTML).toBe(''); unmount(component); }); ``` ### Using Testing Library ```js // component.test.js import { render, screen } from '@testing-library/svelte'; import userEvent from '@testing-library/user-event'; import { expect, test } from 'vitest'; import Component from './Component.svelte'; test('Component', async () => { const user = userEvent.setup(); render(Component); const button = screen.getByRole('button'); expect(button).toHaveTextContent(0); await user.click(button); expect(button).toHaveTextContent(1); }); ``` ## E2E Testing with Playwright ### Setup Install via VS Code extension or: ```bash npm init playwright ``` Configure Playwright: ```js // playwright.config.js const config = { webServer: { command: 'npm run build && npm run preview', port: 4173 }, testDir: 'tests', testMatch: /(.+\.)?(test|spec)\.[jt]s/ }; export default config; ``` ### Writing Tests ```js // tests/hello-world.spec.js import { expect, test } from '@playwright/test'; test('home page has expected h1', async ({ page }) => { await page.goto('/'); await expect(page.locator('h1')).toBeVisible(); }); ``` ## docs/svelte/07-misc/03-typescript.md # Svelte 5 TypeScript Guide ## Basic Usage Add `lang="ts"` to script tags: ```svelte ``` Only type-only features are supported without preprocessors. Unsupported features: - enums - access modifiers with initializers - non-ECMAScript standard features ## Setup ### SvelteKit/Vite (Recommended) ```ts // svelte.config.js import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; const config = { preprocess: vitePreprocess() }; export default config; ``` For non-type-only features: ```ts // svelte.config.js import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; const config = { preprocess: vitePreprocess({ script: true }) }; export default config; ``` ### tsconfig.json Requirements - `target`: at least `ES2022` or `ES2015` with `useDefineForClassFields` - `verbatimModuleSyntax`: `true` - `isolatedModules`: `true` ## Typing Components ### $props ```svelte ``` ### Generic Components ```svelte ``` ### Wrapper Components ```svelte ``` For elements without dedicated types: ```svelte ``` ## Typing Runes ### $state ```ts let count: number = $state(0); ``` For undefined initial values: ```ts class Counter { count = $state() as number; constructor(initial: number) { this.count = initial; } } ``` ## Component Types ### Component Type ```svelte ``` ### ComponentProps ```ts import type { Component, ComponentProps } from 'svelte'; import MyComponent from './MyComponent.svelte'; function withProps>( component: TComponent, props: ComponentProps ) {} withProps(MyComponent, { foo: 'bar' }); ``` ### Component Instance ```svelte ``` ## Extending DOM Types For custom elements or attributes: ```ts // additional-svelte-typings.d.ts declare namespace svelteHTML { interface IntrinsicElements { 'my-custom-element': { someattribute: string; 'on:event': (e: CustomEvent) => void }; } interface HTMLAttributes { onbeforeinstallprompt?: (event: any) => any; mycustomattribute?: any; } } ``` Or by augmenting modules: ```ts // additional-svelte-typings.d.ts import { HTMLButtonAttributes } from 'svelte/elements'; declare module 'svelte/elements' { export interface SvelteHTMLElements { 'custom-button': HTMLButtonAttributes; } export interface HTMLButtonAttributes { veryexperimentalattribute?: string; } } export {}; ``` ## docs/kit/10-getting-started/10-introduction.md # SvelteKit Introduction ## What is SvelteKit? SvelteKit is a framework for building web applications using Svelte. Similar to Next.js (React) or Nuxt (Vue). ## What is Svelte? Svelte is a UI component compiler that converts components into optimized JavaScript and CSS. ## SvelteKit vs Svelte Svelte handles UI components. SvelteKit provides a complete application framework with: - Router for client-side navigation - Build optimizations for minimal code loading - Offline support via service workers - Page preloading - Configurable rendering (SSR, CSR, prerendering) - Image optimization - HMR development experience via Vite ## Key Concepts SvelteKit handles the complex infrastructure so you can focus on building your application. It follows modern web development best practices out of the box. For beginners, check out the [interactive tutorial](/tutorial/kit) or get help in [Discord](/chat). ## docs/kit/10-getting-started/20-creating-a-project.md # Creating a SvelteKit Project ```bash npx sv create my-app cd my-app npm install npm run dev ``` This scaffolds a new project, installs dependencies, and starts a server on [localhost:5173](http://localhost:5173). ## Core Concepts - Pages are Svelte components - Pages are created by adding files to `src/routes` - Pages are server-rendered first, then hydrated as a client-side app ## Editor Setup - Recommended: [VS Code](https://code.visualstudio.com/download) with [Svelte extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) - [Other editor support](https://sveltesociety.dev/resources#editor-support) ## docs/kit/10-getting-started/25-project-types.md # Project Types in SvelteKit SvelteKit offers configurable rendering to build various application types. Rendering settings can be mixed to optimize different parts of your application. ## Default Rendering - First page: Server-side rendering (SSR) - Subsequent pages: Client-side rendering (CSR) - Benefits: Better SEO, perceived performance, and smooth navigation ## Static Site Generation (SSG) ```js // Use adapter-static // In svelte.config.js import adapter from '@sveltejs/adapter-static'; export default { kit: { adapter: adapter() } }; // Prerender specific pages with // +page.js or +page.server.js export const prerender = true; ``` ## Single-Page App (SPA) ```js // In src/routes/+layout.js export const ssr = false; ``` ## Multi-Page App ```html About ``` ## Deployment Options - **Separate Backend**: Deploy SvelteKit frontend separately using `adapter-node` or serverless adapters - **Serverless**: Use `adapter-auto` (default), `adapter-vercel`, `adapter-netlify`, or `adapter-cloudflare` - **Own Server/Container**: Use `adapter-node` - **Library**: Use `@sveltejs/package` add-on - **Offline/PWA**: Leverage [service workers](service-workers) - **Mobile Apps**: Use Tauri or Capacitor with a SvelteKit SPA - **Desktop Apps**: Use Tauri, Wails, or Electron with a SvelteKit SPA - **Browser Extensions**: Use `adapter-static` or community adapters - **Embedded Devices**: Consider `bundleStrategy: 'single'` to reduce concurrent requests For mobile, desktop, and embedded applications, use: ```js // svelte.config.js export default { kit: { output: { bundleStrategy: 'single' } } }; ``` ## docs/kit/10-getting-started/30-project-structure.md # Project Structure in SvelteKit A typical SvelteKit project structure: ```bash my-project/ โ”œ src/ โ”‚ โ”œ lib/ โ”‚ โ”‚ โ”œ server/ # Server-only code โ”‚ โ”‚ โ”” [lib files] # Shared components/utilities โ”‚ โ”œ params/ # Param matchers โ”‚ โ”œ routes/ # Application routes โ”‚ โ”œ app.html # Page template โ”‚ โ”œ error.html # Error page โ”‚ โ”œ hooks.client.js โ”‚ โ”œ hooks.server.js โ”‚ โ”” service-worker.js โ”œ static/ # Static assets โ”œ tests/ # Tests โ”œ package.json โ”œ svelte.config.js โ”œ tsconfig.json โ”” vite.config.js ``` ## Key Files ### src/app.html Page template with placeholders: - `%sveltekit.head%` - Links, scripts, and `` content - `%sveltekit.body%` - Rendered page markup (place inside a container element) - `%sveltekit.assets%` - Path to assets - `%sveltekit.nonce%` - CSP nonce - `%sveltekit.env.[NAME]%` - Environment variables (must start with public prefix) ### src/error.html Fallback error page with placeholders: - `%sveltekit.status%` - HTTP status - `%sveltekit.error.message%` - Error message ### src/lib Library code importable via `$lib` alias. Server-only code in `lib/server` is importable via `$lib/server` and protected from client imports. ### src/routes Contains application routes and route-specific components. ### static Static assets served as-is (favicon, robots.txt, etc.). ### Configuration Files - **package.json**: Must include `@sveltejs/kit`, `svelte`, and `vite` as `devDependencies`. Uses `"type": "module"`. - **svelte.config.js**: Svelte and SvelteKit configuration. - **tsconfig.json**: TypeScript configuration (extends `.svelte-kit/tsconfig.json`). - **vite.config.js**: Vite configuration with `@sveltejs/kit/vite` plugin. ### Generated Files The `.svelte-kit` directory contains generated files that can be safely ignored or deleted (they'll be regenerated). ## docs/kit/10-getting-started/40-web-standards.md # Svelte Web Standards ## Fetch APIs SvelteKit uses standard `fetch` for network requests in hooks, server routes, and browser. ```js // Special fetch in load functions, server hooks, API routes // Allows direct endpoint invocation during SSR without HTTP calls // Preserves credentials and supports relative requests ``` ### Request ```js // Access in hooks and server routes as event.request // Methods: request.json(), request.formData() ``` ### Response ```js // Returned from fetch() and +server.js handlers // A SvelteKit app turns a Request into a Response ``` ### Headers ```js /// file: src/routes/what-is-my-user-agent/+server.js import { json } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export function GET({ request }) { // log all headers console.log(...request.headers); // create a JSON Response using a header we received return json({ // retrieve a specific header userAgent: request.headers.get('user-agent') }, { // set a header on the response headers: { 'x-custom-header': 'potato' } }); } ``` ## FormData ```js /// file: src/routes/hello/+server.js import { json } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export async function POST(event) { const body = await event.request.formData(); // log all fields console.log([...body]); return json({ // get a specific field's value name: body.get('name') ?? 'world' }); } ``` ## Stream APIs Use `ReadableStream`, `WritableStream`, and `TransformStream` for large responses or chunked data. ## URL APIs `URL` interface provides properties like `origin` and `pathname`. Available as `event.url` in hooks/server routes, `page.url` in pages, and `from`/`to` in navigation functions. ### URLSearchParams ```js const foo = url.searchParams.get('foo'); ``` ## Web Crypto ```js const uuid = crypto.randomUUID(); ``` ## docs/kit/20-core-concepts/10-routing.md # SvelteKit Routing ## +page ### +page.svelte Defines a page component rendered on server (SSR) and browser (CSR). ```svelte

    Hello and welcome to my site!

    About my site ``` Receive data from load functions: ```svelte

    {data.title}

    {@html data.content}
    ``` ### +page.js Load data for pages: ```js import { error } from '@sveltejs/kit'; /** @type {import('./$types').PageLoad} */ export function load({ params }) { if (params.slug === 'hello-world') { return { title: 'Hello world!', content: 'Welcome to our blog. Lorem ipsum dolor sit amet...' }; } error(404, 'Not found'); } ``` Configure page behavior with exports: - `export const prerender = true|false|'auto'` - `export const ssr = true|false` - `export const csr = true|false` ### +page.server.js Server-only load functions: ```js import { error } from '@sveltejs/kit'; /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { const post = await getPostFromDatabase(params.slug); if (post) { return post; } error(404, 'Not found'); } ``` Also supports form actions. ## +error Custom error pages: ```svelte

    {page.status}: {page.error.message}

    ``` SvelteKit walks up the tree to find the closest error boundary. ## +layout ### +layout.svelte Shared UI elements across multiple pages: ```svelte {@render children()} ``` Layouts can be nested: ```svelte

    Settings

    {@render children()} ``` ### +layout.js Load data for layouts: ```js /** @type {import('./$types').LayoutLoad} */ export function load() { return { sections: [ { slug: 'profile', title: 'Profile' }, { slug: 'notifications', title: 'Notifications' } ] }; } ``` ### +layout.server.js Server-only layout data loading. ## +server API routes with HTTP verb handlers: ```js import { error } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export function GET({ url }) { const min = Number(url.searchParams.get('min') ?? '0'); const max = Number(url.searchParams.get('max') ?? '1'); const d = max - min; if (isNaN(d) || d < 0) { error(400, 'min and max must be numbers, and min must be less than max'); } const random = min + Math.random() * d; return new Response(String(random)); } ``` Handling POST requests: ```js import { json } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export async function POST({ request }) { const { a, b } = await request.json(); return json(a + b); } ``` Fallback handler for unhandled methods: ```js /** @type {import('./$types').RequestHandler} */ export async function fallback({ request }) { return text(`I caught your ${request.method} request!`); } ``` Content negotiation: SvelteKit determines whether to serve a page or API response based on the `accept` header. ## $types TypeScript definitions for route files: - `PageProps`/`LayoutProps` - For component props - `PageLoad`/`PageServerLoad`/`LayoutLoad`/`LayoutServerLoad` - For load functions - `RequestHandler` - For server endpoints ## docs/kit/20-core-concepts/20-load.md # Loading Data in SvelteKit ## Page Data Load data with `+page.js` (universal) or `+page.server.js` (server-only): ```js /// file: src/routes/blog/[slug]/+page.server.js /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { return { post: await db.getPost(params.slug) }; } ``` ```svelte

    {data.post.title}

    {@html data.post.content}
    ``` ## Layout Data Layout data is available to child layouts and pages: ```js /// file: src/routes/blog/[slug]/+layout.server.js /** @type {import('./$types').LayoutServerLoad} */ export async function load() { return { posts: await db.getPostSummaries() }; } ``` ```svelte
    {@render children()}
    ``` ## page.data Access data from any route component via `page.data`: ```svelte {page.data.title} ``` ## Universal vs Server Load Functions **Server load functions** (`+page.server.js`, `+layout.server.js`): - Always run on server - Can access database, filesystem, private env vars - Must return serializable data - Have access to `cookies`, `locals`, etc. **Universal load functions** (`+page.js`, `+layout.js`): - Run on server during SSR, then in browser - Good for fetching from public APIs - Can return non-serializable data (like component constructors) - Receive server load data via `data` property ## URL Data Access URL data via: ```js /** @type {import('./$types').PageLoad} */ export function load({ url, route, params }) { console.log(url.pathname); // Current path console.log(url.searchParams); // Query parameters console.log(route.id); // '/a/[b]/[...c]' console.log(params.slug); // Dynamic route parameter } ``` ## Making Fetch Requests Use the provided `fetch` function: ```js /** @type {import('./$types').PageLoad} */ export async function load({ fetch, params }) { const res = await fetch(`/api/items/${params.id}`); const item = await res.json(); return { item }; } ``` ## Cookies Server load functions can get/set cookies: ```js /** @type {import('./$types').LayoutServerLoad} */ export async function load({ cookies }) { const sessionid = cookies.get('sessionid'); return { user: await db.getUser(sessionid) }; } ``` ## Headers Set response headers with `setHeaders`: ```js /** @type {import('./$types').PageLoad} */ export async function load({ fetch, setHeaders }) { const response = await fetch(url); setHeaders({ 'cache-control': response.headers.get('cache-control') }); return response.json(); } ``` ## Using Parent Data Access parent data with `await parent()`: ```js /** @type {import('./$types').PageLoad} */ export async function load({ parent }) { const { a, b } = await parent(); return { c: a + b }; } ``` ## Errors and Redirects Throw errors or redirects: ```js import { error, redirect } from '@sveltejs/kit'; /** @type {import('./$types').LayoutServerLoad} */ export function load({ locals }) { if (!locals.user) { redirect(307, '/login'); } if (!locals.user.isAdmin) { error(403, 'not an admin'); } } ``` ## Streaming with Promises Server load functions can return promises for streaming: ```js /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { return { comments: loadComments(params.slug), post: await loadPost(params.slug) }; } ``` ```svelte {#await data.comments} Loading comments... {:then comments} {#each comments as comment}

    {comment.content}

    {/each} {:catch error}

    Error: {error.message}

    {/await} ``` ## Rerunning Load Functions Load functions rerun when: - Referenced `params` or `url` properties change - Parent load function reruns (if using `await parent()`) - Manually invalidated with `invalidate()` or `invalidateAll()` ### Manual Invalidation ```js /** @type {import('./$types').PageLoad} */ export async function load({ fetch, depends }) { depends('app:random'); const response = await fetch('https://api.example.com/random-number'); return { number: await response.json() }; } ``` ```svelte ``` ## Using getRequestEvent Access request event in shared server code: ```js // src/lib/server/auth.js import { redirect } from '@sveltejs/kit'; import { getRequestEvent } from '$app/server'; export function requireLogin() { const { locals, url } = getRequestEvent(); if (!locals.user) { redirect(307, `/login?${new URLSearchParams({ redirectTo: url.pathname + url.search })}`); } return locals.user; } ``` ## docs/kit/20-core-concepts/30-form-actions.md # Svelte Form Actions ## Default Actions Define a default action in `+page.server.js`: ```js /// file: src/routes/login/+page.server.js export const actions = { default: async (event) => { // TODO log the user in } }; ``` Use it with a simple form: ```svelte
    ``` Target actions from other pages: ```html
    ``` ## Named Actions Multiple actions in one page: ```js export const actions = { login: async (event) => { // TODO log the user in }, register: async (event) => { // TODO register the user } }; ``` Invoke with query parameter: ```svelte
    ``` Use `formaction` for multiple actions in one form: ```svelte
    ``` ## Action Anatomy Actions receive a `RequestEvent` and can return data: ```js import * as db from '$lib/server/db'; export const actions = { login: async ({ cookies, request }) => { const data = await request.formData(); const email = data.get('email'); const password = data.get('password'); const user = await db.getUser(email); cookies.set('sessionid', await db.createSession(user), { path: '/' }); return { success: true }; } }; ``` Access returned data in the page: ```svelte {#if form?.success}

    Successfully logged in! Welcome back, {data.user.name}

    {/if} ``` ### Validation Errors Return validation errors with the `fail` function: ```js import { fail } from '@sveltejs/kit'; export const actions = { login: async ({ cookies, request }) => { const data = await request.formData(); const email = data.get('email'); const password = data.get('password'); if (!email) { return fail(400, { email, missing: true }); } const user = await db.getUser(email); if (!user || user.password !== db.hash(password)) { return fail(400, { email, incorrect: true }); } // Success case } }; ``` Display errors in the form: ```svelte
    {#if form?.missing}

    The email field is required

    {/if} {#if form?.incorrect}

    Invalid credentials!

    {/if}
    ``` ### Redirects Redirect after an action: ```js import { fail, redirect } from '@sveltejs/kit'; export const actions = { login: async ({ cookies, request, url }) => { // Authentication logic if (url.searchParams.has('redirectTo')) { redirect(303, url.searchParams.get('redirectTo')); } return { success: true }; } }; ``` ## Loading Data After an action runs, the page's `load` functions run again. Update `event.locals` when setting cookies: ```js // In action event.cookies.delete('sessionid', { path: '/' }); event.locals.user = null; ``` ## Progressive Enhancement ### use:enhance Basic enhancement: ```svelte
    ``` ### Customizing use:enhance ```svelte { // Pre-submission logic return async ({ result, update }) => { // Post-submission logic }; }} > ``` Custom handling with `applyAction`: ```svelte { return async ({ result }) => { if (result.type === 'redirect') { goto(result.location); } else { await applyAction(result); } }; }} > ``` ### Custom Event Listener Manual form submission: ```svelte
    ``` To target actions in `+page.server.js` explicitly: ```js const response = await fetch(this.action, { method: 'POST', body: data, headers: { 'x-sveltekit-action': 'true' } }); ``` ## GET vs POST For non-data-modifying forms, use `method="GET"`: ```html
    ``` This navigates to `/search?q=...` using client-side routing without invoking an action. ## docs/kit/20-core-concepts/40-page-options.md # Svelte 5 Page Options ## Core Concepts ### Rendering Modes SvelteKit supports three rendering strategies: - **Server-Side Rendering (SSR)**: Default mode - renders on server first, then hydrates in browser - **Client-Side Rendering (CSR)**: Interactive components rendered in browser - **Prerendering**: Generate static HTML at build time Options can be set in `+page.js`, `+page.server.js`, `+layout.js`, or `+layout.server.js`. Child layouts/pages override parent settings. ## Page Options ### prerender ```js // Static generation at build time export const prerender = true; // Enable prerendering for this route export const prerender = false; // Disable prerendering export const prerender = 'auto'; // Prerender but keep in SSR manifest ``` **Notes:** - Prerendering crawls your app starting from the root - Routes with `prerender = true` are excluded from SSR manifests - For fully static sites, use `adapter-static` - During prerendering, `building` from `$app/environment` is `true` **When not to prerender:** - When users need different content (authentication, personalization) - Pages with form actions - Pages that access `url.searchParams` during prerendering **Route conflicts:** - Use file extensions for server routes (`foo.json` instead of `foo`) - Pages are written as `foo/index.html` instead of `foo` ### entries For dynamic routes that should be prerendered: ```js // src/routes/blog/[slug]/+page.server.js export function entries() { return [ { slug: 'hello-world' }, { slug: 'another-blog-post' } ]; } export const prerender = true; ``` Can be async to fetch data from CMS/database. ### ssr ```js export const ssr = false; // Disable server-side rendering ``` Renders empty shell page instead of full HTML. Useful for browser-only code but generally not recommended. ### csr ```js export const csr = false; // Disable client-side rendering ``` When disabled: - No JavaScript is sent to client - Page works with HTML/CSS only - No form progressive enhancement - Links cause full-page navigation - HMR is disabled For development-only CSR: ```js import { dev } from '$app/environment'; export const csr = dev; ``` ### trailingSlash ```js export const trailingSlash = 'never'; // Default - redirects /about/ to /about export const trailingSlash = 'always'; // Redirects /about to /about/ export const trailingSlash = 'ignore'; // Treats both forms as valid ``` Affects prerendering output: `always` creates `about/index.html`, otherwise creates `about.html`. ### config Platform-specific configuration for adapters: ```js /** @type {import('some-adapter').Config} */ export const config = { runtime: 'edge' }; ``` Config objects merge at top level but not deeper levels. ## docs/kit/20-core-concepts/50-state-management.md # Svelte 5 State Management ## Server State Guidelines ### Avoid Shared State on Server Servers are stateless and shared by multiple users. Never store user data in shared variables: ```js // NEVER DO THIS - shared variable exposes data between users let user; export function load() { return { user }; } export const actions = { default: async ({ request }) => { const data = await request.formData(); user = { name: data.get('name') }; // BAD: shared between users } } ``` Instead, authenticate users with cookies and store data in databases. ### No Side-Effects in Load Load functions should be pure: ```js // NEVER DO THIS - modifies global state import { user } from '$lib/user'; export async function load({ fetch }) { const response = await fetch('/api/user'); user.set(await response.json()); // BAD: affects all users } ``` Instead, return the data: ```js export async function load({ fetch }) { const response = await fetch('/api/user'); return { user: await response.json() }; } ``` ## Using Context for State Use Svelte's context API for component-scoped state: ```svelte ``` ```svelte

    Welcome {user().name}

    ``` ## Component State Preservation Components are reused during navigation. Reactive values must be properly declared: ```svelte ``` Correct approach: ```svelte ``` To force component remounting on navigation: ```svelte {#key page.url.pathname} {/key} ``` ## State Storage Options - **URL Parameters**: For state that should survive reloads (filters, sorting) - Access via `url` in load functions or `page.url.searchParams` in components - **Snapshots**: For ephemeral UI state (accordion open/closed) - Persists during navigation but not page reloads ## docs/kit/25-build-and-deploy/10-building-your-app.md # Building your app ## Build Process SvelteKit builds in two stages when running `vite build`: 1. Vite creates optimized production builds of server code, browser code, and service worker 2. An adapter tunes the build for your target environment ## During the build Skip code execution during build phase: ```js import { building } from '$app/environment'; import { setupMyDatabase } from '$lib/server/database'; if (!building) { setupMyDatabase(); } export function load() { // ... } ``` ## Preview Preview production build locally with `vite preview` (via `npm run preview`). Note that this runs in Node and doesn't perfectly reproduce deployment environment (adapter-specific features like the `platform` object aren't available). ## docs/kit/25-build-and-deploy/20-adapters.md # Adapters Adapters convert your SvelteKit app for deployment to specific platforms. ## Official Adapters - `@sveltejs/adapter-cloudflare` - For Cloudflare Workers/Pages - `@sveltejs/adapter-netlify` - For Netlify - `@sveltejs/adapter-node` - For Node servers - `@sveltejs/adapter-static` - For static site generation (SSG) - `@sveltejs/adapter-vercel` - For Vercel Community adapters available at [sveltesociety.dev](https://sveltesociety.dev/packages?category=sveltekit-adapters). ## Configuration Specify your adapter in `svelte.config.js`: ```js /// file: svelte.config.js import adapter from 'svelte-adapter-foo'; /** @type {import('@sveltejs/kit').Config} */ const config = { kit: { adapter: adapter({ // adapter options go here }) } }; export default config; ``` ## Platform-specific Context Adapters may provide platform-specific information via the `platform` property in the `RequestEvent` object used in hooks and server routes. Check adapter documentation for details. ## docs/kit/25-build-and-deploy/55-single-page-apps.md # Single-page apps in SvelteKit ## Basic Setup Convert any SvelteKit app to a SPA by disabling SSR in the root layout: ```js /// file: src/routes/+layout.js export const ssr = false; ``` > **Note**: Not recommended for most cases due to SEO, performance, and accessibility issues. ## Using adapter-static For apps without server-side logic, use `adapter-static` with a fallback page: ```js /// file: svelte.config.js import adapter from '@sveltejs/adapter-static'; export default { kit: { adapter: adapter({ fallback: '200.html' // platform-specific }) } }; ``` The fallback page loads your app and navigates to the correct route. The filename varies by hosting platform. ## Apache Configuration For Apache, add a `static/.htaccess` file: ``` RewriteEngine On RewriteBase / RewriteRule ^200\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /200.html [L] ``` ## Selective Prerendering Enable prerendering for specific pages: ```js /// file: src/routes/my-prerendered-page/+page.js export const prerender = true; export const ssr = true; ``` ## docs/kit/30-advanced/10-advanced-routing.md # Advanced Routing in SvelteKit ## Rest Parameters Use rest syntax for unknown number of route segments: ```bash /[org]/[repo]/tree/[branch]/[...file] ``` For `/sveltejs/kit/tree/main/documentation/docs/04-advanced-routing.md`: ```js { org: 'sveltejs', repo: 'kit', branch: 'main', file: 'documentation/docs/04-advanced-routing.md' } ``` > Note: `src/routes/a/[...rest]/z/+page.svelte` matches `/a/z`, `/a/b/z`, etc. Always validate rest parameters. ### 404 Pages For custom 404s with nested routes, create a catch-all route: ```js /// file: src/routes/marx-brothers/[...path]/+page.js import { error } from '@sveltejs/kit'; /** @type {import('./$types').PageLoad} */ export function load(event) { error(404, 'Not Found'); } ``` ## Optional Parameters Make parameters optional with double brackets: `[[lang]]/home` This matches both `/home` and `/en/home`. > Note: Optional parameters can't follow rest parameters. ## Matching Ensure parameters are well-formed with matchers: ```js /// file: src/params/fruit.js /** * @param {string} param * @return {param is ('apple' | 'orange')} * @satisfies {import('@sveltejs/kit').ParamMatcher} */ export function match(param) { return param === 'apple' || param === 'orange'; } ``` Use in routes: ``` src/routes/fruits/[page=fruit] ``` ## Sorting Routes are sorted by: 1. Specificity (non-parameterized > parameterized) 2. Matchers (routes with matchers > without) 3. Optional/rest parameters (lowest priority) 4. Alphabetically (ties) ## Encoding Use hexadecimal escape sequences for special characters: - `[x+5c]` for `\` - `[x+2f]` for `/` - `[x+23]` for `#` - etc. Unicode escape sequences: `[u+nnnn]` (e.g., `[u+d83e][u+dd2a]` = `๐Ÿคช`) ## Advanced Layouts ### (group) Group routes without affecting URL paths: ```tree src/routes/ โ”‚ (app)/ โ”‚ โ”œ dashboard/ โ”‚ โ”œ item/ โ”‚ โ”” +layout.svelte โ”‚ (marketing)/ โ”‚ โ”œ about/ โ”‚ โ”œ testimonials/ โ”‚ โ”” +layout.svelte โ”œ admin/ โ”” +layout.svelte ``` ### Breaking Out of Layouts Use `@` to specify parent layout: - `+page@[id].svelte` - inherits from nearest `[id]` layout - `+page@item.svelte` - inherits from nearest `item` layout - `+page@(app).svelte` - inherits from nearest `(app)` layout - `+page@.svelte` - inherits from root layout Layouts can also break out with `+layout@.svelte`. Consider composition alternatives for complex cases: ```svelte {@render children()} ``` ## docs/kit/30-advanced/20-hooks.md # SvelteKit Hooks Hooks are app-wide functions that SvelteKit calls in response to specific events. ## Files - `src/hooks.server.js` - server hooks - `src/hooks.client.js` - client hooks - `src/hooks.js` - universal hooks (both client and server) ## Server Hooks ### handle Runs on every request to determine the response. ```js /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { if (event.url.pathname.startsWith('/custom')) { return new Response('custom response'); } const response = await resolve(event); return response; } ``` `resolve` accepts optional parameters: - `transformPageChunk({ html, done })` - transforms HTML chunks - `filterSerializedResponseHeaders(name, value)` - filters headers in serialized responses - `preload({ type, path })` - determines files to preload in `` ### handleFetch Modifies `fetch` requests in server-side `load` or `action` functions. ```js /** @type {import('@sveltejs/kit').HandleFetch} */ export async function handleFetch({ request, fetch }) { if (request.url.startsWith('https://api.yourapp.com/')) { request = new Request( request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'), request ); } return fetch(request); } ``` ### locals Add custom data to the request via `event.locals`: ```js /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { event.locals.user = await getUserInformation(event.cookies.get('sessionid')); const response = await resolve(event); return response; } ``` ## Shared Hooks (Server & Client) ### handleError Handles unexpected errors during loading or rendering. ```js /** @type {import('@sveltejs/kit').HandleServerError} */ export async function handleError({ error, event, status, message }) { const errorId = crypto.randomUUID(); // Log to service like Sentry console.error(error); return { message: 'Whoops!', errorId }; } ``` ### init Runs once when server is created or app starts in browser. ```js /** @type {import('@sveltejs/kit').ServerInit} */ export async function init() { await db.connect(); } ``` ## Universal Hooks ### reroute Changes how URLs translate to routes. ```js /** @type {Record} */ const translated = { '/en/about': '/en/about', '/de/ueber-uns': '/de/about', '/fr/a-propos': '/fr/about', }; /** @type {import('@sveltejs/kit').Reroute} */ export function reroute({ url }) { if (url.pathname in translated) { return translated[url.pathname]; } } ``` Can be async since v2.18: ```js /** @type {import('@sveltejs/kit').Reroute} */ export async function reroute({ url, fetch }) { if (url.pathname === '/api/reroute') return; const api = new URL('/api/reroute', url); api.searchParams.set('pathname', url.pathname); const result = await fetch(api).then(r => r.json()); return result.pathname; } ``` ### transport Passes custom types across server/client boundary. ```js /** @type {import('@sveltejs/kit').Transport} */ export const transport = { Vector: { encode: (value) => value instanceof Vector && [value.x, value.y], decode: ([x, y]) => new Vector(x, y) } }; ``` ## docs/kit/30-advanced/25-errors.md # Svelte Errors ## Error Objects SvelteKit handles two types of errors: - Expected errors (created with `error` helper) - Unexpected errors (other exceptions) Both are represented as `{ message: string }` objects by default, but can be extended. ## Expected Errors ```js import { error } from '@sveltejs/kit'; export async function load({ params }) { const post = await db.getPost(params.slug); if (!post) { error(404, { message: 'Not found' }); } return { post }; } ``` Access errors in components: ```svelte

    {page.error.message}

    ``` Shorthand for simple errors: ```js error(404, 'Not found'); // Same as error(404, { message: 'Not found' }) ``` Add custom properties: ```js error(404, { message: 'Not found', code: 'NOT_FOUND' }); ``` ## Unexpected Errors Unexpected errors are any other exceptions. For security, their details aren't exposed to users. Default error shape for users: ```json { "message": "Internal Error" } ``` Use `handleError` hook for custom error handling (reporting, custom responses). ## Error Responses Error handling depends on context: 1. Errors in `handle` or `+server.js`: Returns fallback error page or JSON 2. Errors in `load` functions: Renders nearest `+error.svelte` component 3. Errors in root `+layout.js/+layout.server.js`: Uses fallback error page ### Custom Fallback Error Page Create `src/error.html`: ```html %sveltekit.error.message%

    My custom error page

    Status: %sveltekit.status%

    Message: %sveltekit.error.message%

    ``` ## Type Safety Customize error shape in TypeScript: ```ts declare global { namespace App { interface Error { code: string; id: string; } } } export {}; ``` ## docs/kit/30-advanced/30-link-options.md # SvelteKit Link Options ## Navigation Basics SvelteKit uses standard `` elements for navigation between routes. When clicking a link within your app, SvelteKit: - Imports the code for the new page - Calls necessary `load` functions - Updates the UI without a full page reload ## data-sveltekit-preload-data Controls when data loading begins: ```html
    %sveltekit.body%
    Get current stonk values ``` - `"hover"`: Preloads on mouse hover or touchstart - `"tap"`: Preloads on mousedown or touchstart Preloading is skipped if `navigator.connection.saveData` is true. ## data-sveltekit-preload-code Controls when code loading begins: - `"eager"`: Preloads immediately - `"viewport"`: Preloads when link enters viewport - `"hover"`: Preloads on hover - `"tap"`: Preloads on tap/click Note: `viewport` and `eager` only apply to links present in DOM immediately after navigation. ## data-sveltekit-reload Forces full-page navigation: ```html Path ``` Links with `rel="external"` behave the same and are ignored during prerendering. ## data-sveltekit-replacestate Replaces current history entry instead of creating a new one: ```html Path ``` ## data-sveltekit-keepfocus Maintains focus on the current element after navigation: ```html
    ``` Avoid using on links for accessibility reasons. Only use on elements that exist after navigation. ## data-sveltekit-noscroll Prevents automatic scrolling after navigation: ```html Path ``` ## Disabling Options Disable options by setting value to `"false"`: ```html
    a
    d
    ``` Conditional application: ```svelte
    ``` ## docs/kit/30-advanced/40-service-workers.md # Service Workers in SvelteKit Service workers act as proxy servers for network requests, enabling offline support and faster navigation through precaching. ## Basic Setup SvelteKit automatically registers `src/service-worker.js` (or `src/service-worker/index.js`). ```js // Manual registration (if you disable automatic registration) if ('serviceWorker' in navigator) { addEventListener('load', function () { navigator.serviceWorker.register('./path/to/service-worker.js'); }); } ``` ## Inside the Service Worker Access the `$service-worker` module for paths to assets, build files, and prerendered pages. ```js /// import { build, files, version } from '$service-worker'; // Create a unique cache name for this deployment const CACHE = `cache-${version}`; const ASSETS = [ ...build, // the app itself ...files // everything in `static` ]; self.addEventListener('install', (event) => { // Create a new cache and add all files to it async function addFilesToCache() { const cache = await caches.open(CACHE); await cache.addAll(ASSETS); } event.waitUntil(addFilesToCache()); }); self.addEventListener('activate', (event) => { // Remove previous cached data from disk async function deleteOldCaches() { for (const key of await caches.keys()) { if (key !== CACHE) await caches.delete(key); } } event.waitUntil(deleteOldCaches()); }); self.addEventListener('fetch', (event) => { // ignore POST requests etc if (event.request.method !== 'GET') return; async function respond() { const url = new URL(event.request.url); const cache = await caches.open(CACHE); // `build`/`files` can always be served from the cache if (ASSETS.includes(url.pathname)) { const response = await cache.match(url.pathname); if (response) { return response; } } // for everything else, try the network first, but // fall back to the cache if we're offline try { const response = await fetch(event.request); // if we're offline, fetch can return a value that is not a Response // instead of throwing - and we can't pass this non-Response to respondWith if (!(response instanceof Response)) { throw new Error('invalid response from fetch'); } if (response.status === 200) { cache.put(event.request, response.clone()); } return response; } catch (err) { const response = await cache.match(event.request); if (response) { return response; } // if there's no cache, then just error out throw err; } } event.respondWith(respond()); }); ``` > Be careful with caching - stale data may be worse than unavailable data, and browsers will empty caches if they get too full. ## Development Mode Service workers are bundled for production but not during development. Only browsers supporting modules in service workers will work in dev mode. ```js import { dev } from '$app/environment'; navigator.serviceWorker.register('/service-worker.js', { type: dev ? 'module' : 'classic' }); ``` > `build` and `prerendered` are empty arrays during development ## Type Safety ```js /// /// /// /// const sw = /** @type {ServiceWorkerGlobalScope} */ (/** @type {unknown} */ (self)); ``` ## Alternatives - [Vite PWA plugin](https://vite-pwa-org.netlify.app/frameworks/sveltekit.html) for Workbox integration - [MDN Service Worker docs](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers) ## docs/kit/30-advanced/50-server-only-modules.md # Server-only modules ## Private environment variables `$env/static/private` and `$env/dynamic/private` modules can only be imported into server-side modules like `hooks.server.js` or `+page.server.js`. ## Server-only utilities `$app/server` module (containing `read` function for filesystem access) is server-only. ## Your modules Make your modules server-only by: - Adding `.server` to filename: `secrets.server.js` - Placing in `$lib/server`: `$lib/server/secrets.js` ## How it works SvelteKit prevents importing server-only code in public-facing code: ```js /// file: $lib/server/secrets.js export const atlantisCoordinates = [/* redacted */]; ``` ```js /// file: src/routes/utils.js export { atlantisCoordinates } from '$lib/server/secrets.js'; export const add = (a, b) => a + b; ``` ```html /// file: src/routes/+page.svelte ``` This produces an error: ``` Cannot import $lib/server/secrets.js into public-facing code: src/routes/+page.svelte src/routes/utils.js $lib/server/secrets.js ``` Works with dynamic imports too, with one caveat: during development, illegal imports may not be detected on first load if there are multiple dynamic imports in the chain. > Unit testing frameworks don't distinguish between server-only and public-facing code, so illegal import detection is disabled when `process.env.TEST === 'true'`. ## docs/kit/30-advanced/65-snapshots.md # Snapshots Preserve ephemeral DOM state (form inputs, scroll positions) between navigations. ```svelte