<SYSTEM>This is the abridged developer documentation for Svelte and SvelteKit.</SYSTEM>

# Start of Svelte documentation


# Overview

Svelte is a framework for building user interfaces on the web. It uses a compiler to turn declarative components written in HTML, CSS and JavaScript... ```svelte <!--- file: App.svelte ---> <script> function greet() { alert('Welcome to Svelte!'); } </script> <button onclick={greet}>click me</button> <style> button { font-size: 2em; } </style> ``` ...into lean, tightly optimized JavaScript. You can use it to build anything on the web, from standalone components to ambitious full stack apps (using Svelte's companion application framework, [SvelteKit](../kit)) and everything in between. These pages serve as reference documentation. If you're new to Svelte, we recommend starting with the [interactive tutorial](/tutorial) and coming back here when you have questions. You can also try Svelte online in the [playground](/playground) or, if you need a more fully-featured environment, on [StackBlitz](https://sveltekit.new).

# Getting started

We recommend using [SvelteKit](../kit), the official application framework from the Svelte team powered by [Vite](https://vite.dev/): ```bash npx sv create myapp cd myapp npm install npm run dev ``` Don't worry if you don't know Svelte yet! You can ignore all the nice features SvelteKit brings on top for now and dive into it later. ## Alternatives to SvelteKit You can also use Svelte directly with Vite by running `npm create vite@latest` and selecting the `svelte` option. With this, `npm run build` will generate HTML, JS and CSS files inside the `dist` directory using [vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte). In most cases, you will probably need to [choose a routing library](faq#Is-there-a-router) as well. There are also plugins for [Rollup](https://github.com/sveltejs/rollup-plugin-svelte), [Webpack](https://github.com/sveltejs/svelte-loader) [and a few others](https://sveltesociety.dev/packages?category=build-plugins), but we recommend Vite. ## Editor tooling The Svelte team maintains a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), and there are integrations with various other [editors](https://sveltesociety.dev/resources#editor-support) and tools as well. You can also check your code from the command line using [sv check](https://github.com/sveltejs/cli). ## Getting help Don't be shy about asking for help in the [Discord chatroom](/chat)! You can also find answers on [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte).

# .svelte files

Components are the building blocks of Svelte applications. They are written into `.svelte` files, using a superset of HTML. All three sections — script, styles and markup — are optional. ```svelte /// file: MyComponent.svelte <script module> // module-level logic goes here // (you will rarely use this) </script> <script> // instance-level logic goes here </script> <!-- markup (zero or more items) goes here --> <style> /* styles go here */ </style> ``` ## `<script>` A `<script>` block contains JavaScript (or TypeScript, when adding the `lang="ts"` attribute) that runs when a component instance is created. Variables declared (or imported) at the top level can be referenced in the component's markup. In addition to normal JavaScript, you can use _runes_ to declare [component props]($props) and add reactivity to your component. Runes are covered in the next section. <!-- TODO describe behaviour of `export` --> ## `<script module>` A `<script>` tag with a `module` attribute runs once when the module first evaluates, rather than for each component instance. Variables declared in this block can be referenced elsewhere in the component, but not vice versa. ```svelte <script module> let total = 0; </script> <script> total += 1; console.log(`instantiated ${total} times`); </script> ``` You can `export` bindings from this block, and they will become exports of the compiled module. You cannot `export default`, since the default export is the component itself. > In Svelte 4, this script tag was created using `<script context="module">` ## `<style>` CSS inside a `<style>` block will be scoped to that component. ```svelte <style> p { /* this will only affect <p> elements in this component */ color: burlywood; } </style> ``` For more information, head to the section on [styling](scoped-styles).

# .svelte.js and .svelte.ts files

Besides `.svelte` files, Svelte also operates on `.svelte.js` and `.svelte.ts` files. These behave like any other `.js` or `.ts` module, except that you can use runes. This is useful for creating reusable reactive logic, or sharing reactive state across your app. > This is a concept that didn't exist prior to Svelte 5

# What are runes?

> > A letter or mark used as a mystical or magic symbol. Runes are symbols that you use in `.svelte` and `.svelte.js`/`.svelte.ts` files to control the Svelte compiler. If you think of Svelte as a language, runes are part of the syntax — they are _keywords_. Runes have a `$` prefix and look like functions: ```js let message = $state('hello'); ``` They differ from normal JavaScript functions in important ways, however: - You don't need to import them — they are part of the language - They're not values — you can't assign them to a variable or pass them as arguments to a function - Just like JavaScript keywords, they are only valid in certain positions (the compiler will help you if you put them in the wrong place) > Runes didn't exist prior to Svelte 5.

# $state

The `$state` rune allows you to create _reactive state_, which means that your UI _reacts_ when it changes. ```svelte <script> let count = $state(0); </script> <button onclick={() => count++}> clicks: {count} </button> ``` Unlike other frameworks you may have encountered, there is no API for interacting with state — `count` is just a number, rather than an object or a function, and you can update it like you would update any other variable. ### Deep state If `$state` is used with an array or a simple object, the result is a deeply reactive _state proxy_. [Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) allow Svelte to run code when you read or write properties, including via methods like `array.push(...)`, triggering granular updates. State is proxified recursively until Svelte finds something other than an array or simple object. In a case like this... ```js let todos = $state([ { done: false, text: 'add more todos' } ]); ``` ...modifying an individual todo's property will trigger updates to anything in your UI that depends on that specific property: ```js let todos = [{ done: false, text: 'add more todos' }]; // ---cut--- todos[0].done = !todos[0].done; ``` If you push a new object to the array, it will also be proxified: ```js let todos = [{ done: false, text: 'add more todos' }]; // ---cut--- todos.push({ done: false, text: 'eat lunch' }); ``` Note that if you destructure a reactive value, the references are not reactive — as in normal JavaScript, they are evaluated at the point of destructuring: ```js let todos = [{ done: false, text: 'add more todos' }]; // ---cut--- let { done, text } = todos[0]; // this will not affect the value of `done` todos[0].done = !todos[0].done; ``` ### Classes You can also use `$state` in class fields (whether public or private): ```js // @errors: 7006 2554 class Todo { done = $state(false); text = $state(); constructor(text) { this.text = text; } reset() { this.text = ''; this.done = false; } } ``` When calling methods in JavaScript, the value of [`this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) matters. This won't work, because `this` inside the `reset` method will be the `<button>` rather than the `Todo`: ```svelte <button onclick={todo.reset}> reset </button> ``` You can either use an inline function... ```svelte <button onclick=+++{() => todo.reset()}>+++ reset </button> ``` ...or use an arrow function in the class definition: ```js // @errors: 7006 2554 class Todo { done = $state(false); text = $state(); constructor(text) { this.text = text; } +++reset = () => {+++ this.text = ''; this.done = false; } } ``` ## `$state.raw` In cases where you don't want objects and arrays to be deeply reactive you can use `$state.raw`. State declared with `$state.raw` cannot be mutated; it can only be _reassigned_. In other words, rather than assigning to a property of an object, or using an array method like `push`, replace the object or array altogether if you'd like to update it: ```js let person = $state.raw({ name: 'Heraclitus', age: 49 }); // this will have no effect person.age += 1; // this will work, because we're creating a new person person = { name: 'Heraclitus', age: 50 }; ``` This can improve performance with large arrays and objects that you weren't planning to mutate anyway, since it avoids the cost of making them reactive. Note that raw state can _contain_ reactive state (for example, a raw array of reactive objects). ## `$state.snapshot` To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`: ```svelte <script> let counter = $state({ count: 0 }); function onclick() { // Will log `{ count: ... }` rather than `Proxy { ... }` console.log($state.snapshot(counter)); } </script> ``` This is handy when you want to pass some state to an external library or API that doesn't expect a proxy, such as `structuredClone`. ## Passing state into functions JavaScript is a _pass-by-value_ language — when you call a function, the arguments are the _values_ rather than the _variables_. In other words: ```js /// file: index.js // @filename: index.js // ---cut--- /** * @param {number} a * @param {number} b */ function add(a, b) { return a + b; } let a = 1; let b = 2; let total = add(a, b); console.log(total); // 3 a = 3; b = 4; console.log(total); // still 3! ``` If `add` wanted to have access to the _current_ values of `a` and `b`, and to return the current `total` value, you would need to use functions instead: ```js /// file: index.js // @filename: index.js // ---cut--- /** * @param {() => number} getA * @param {() => number} getB */ 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 ``` State in Svelte is no different — when you reference something declared with the `$state` rune... ```js let a = +++$state(1)+++; let b = +++$state(2)+++; ``` ...you're accessing its _current value_. Note that 'functions' is broad — it encompasses properties of proxies and [`get`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)/[`set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) properties... ```js /// file: index.js // @filename: index.js // ---cut--- /** * @param {{ a: number, b: number }} input */ 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 ``` ...though if you find yourself writing code like that, consider using [classes](#Classes) instead.

# $derived

Derived state is declared with the `$derived` rune: ```svelte <script> let count = $state(0); let doubled = $derived(count * 2); </script> <button onclick={() => count++}> {doubled} </button> <p>{count} doubled is {doubled}</p> ``` The expression inside `$derived(...)` should be free of side-effects. Svelte will disallow state changes (e.g. `count++`) inside derived expressions. As with `$state`, you can mark class fields as `$derived`. ## `$derived.by` Sometimes you need to create complex derivations that don't fit inside a short expression. In these cases, you can use `$derived.by` which accepts a function as its argument. ```svelte <script> let numbers = $state([1, 2, 3]); let total = $derived.by(() => { let total = 0; for (const n of numbers) { total += n; } return total; }); </script> <button onclick={() => numbers.push(numbers.length + 1)}> {numbers.join(' + ')} = {total} </button> ``` In essence, `$derived(expression)` is equivalent to `$derived.by(() => expression)`. ## Understanding dependencies Anything read synchronously inside the `$derived` expression (or `$derived.by` function body) is considered a _dependency_ of the derived state. When the state changes, the derived will be marked as _dirty_ and recalculated when it is next read. To exempt a piece of state from being treated as a dependency, use [`untrack`](svelte#untrack). ## Update propagation Svelte uses something called _push-pull reactivity_ — when state is updated, everything that depends on the state (whether directly or indirectly) is immediately notified of the change (the 'push'), but derived values are not re-evaluated until they are actually read (the 'pull'). If the new value of a derived is referentially identical to its previous value, downstream updates will be skipped. In other words, Svelte will only update the text inside the button when `large` changes, not when `count` changes, even though `large` depends on `count`: ```svelte <script> let count = $state(0); let large = $derived(count > 10); </script> <button onclick={() => count++}> {large} </button> ```

# $effect

Effects are what make your application _do things_. When Svelte runs an effect function, it tracks which pieces of state (and derived state) are accessed (unless accessed inside [`untrack`](svelte#untrack)), and re-runs the function when that state later changes. Most of the effects in a Svelte app are created by Svelte itself — they're the bits that update the text in `<h1>hello {name}!</h1>` when `name` changes, for example. But you can also create your own effects with the `$effect` rune, which is useful when you need to synchronize an external system (whether that's a library, or a `<canvas>` element, or something across a network) with state inside your Svelte app. Your effects run after the component has been mounted to the DOM, and in a [microtask](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide) after state changes ([demo](/REMOVED)): ```svelte <script> let size = $state(50); let color = $state('#ff3e00'); let canvas; $effect(() => { const context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); // this will re-run whenever `color` or `size` change context.fillStyle = color; context.fillRect(0, 0, size, size); }); </script> <canvas bind:this={canvas} width="100" height="100" /> ``` Re-runs are batched (i.e. changing `color` and `size` in the same moment won't cause two separate runs), and happen after any DOM updates have been applied. You can place `$effect` anywhere, not just at the top level of a component, as long as it is called during component initialization (or while a parent effect is active). It is then tied to the lifecycle of the component (or parent effect) and will therefore destroy itself when the component unmounts (or the parent effect is destroyed). You can return a function from `$effect`, which will run immediately before the effect re-runs, and before it is destroyed ([demo](/REMOVED)). ```svelte <script> let count = $state(0); let milliseconds = $state(1000); $effect(() => { // This will be recreated whenever `milliseconds` changes const interval = setInterval(() => { count += 1; }, milliseconds); return () => { // if a callback is provided, it will run // a) immediately before the effect re-runs // b) when the component is destroyed clearInterval(interval); }; }); </script> <h1>{count}</h1> <button onclick={() => (milliseconds *= 2)}>slower</button> <button onclick={() => (milliseconds /= 2)}>faster</button> ``` ### Understanding dependencies `$effect` automatically picks up any reactive values (`$state`, `$derived`, `$props`) that are _synchronously_ read inside its function body (including indirectly, via function calls) and registers them as dependencies. When those dependencies change, the `$effect` schedules a rerun. Values that are read _asynchronously_ — after an `await` or inside a `setTimeout`, for example — will not be tracked. Here, the canvas will be repainted when `color` changes, but not when `size` changes ([demo](/REMOVED)): ```ts // @filename: index.ts declare let canvas: { width: number; height: number; getContext(type: '2d', options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D; }; declare let color: string; declare let size: number; // ---cut--- $effect(() => { const context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); // this will re-run whenever `color` changes... context.fillStyle = color; setTimeout(() => { // ...but not when `size` changes context.fillRect(0, 0, size, size); }, 0); }); ``` An effect only reruns when the object it reads changes, not when a property inside it changes. (If you want to observe changes _inside_ an object at dev time, you can use [`$inspect`]($inspect).) ```svelte <script> let state = $state({ value: 0 }); let derived = $derived({ value: state.value * 2 }); // this will run once, because `state` is never reassigned (only mutated) $effect(() => { state; }); // this will run whenever `state.value` changes... $effect(() => { state.value; }); // ...and so will this, because `derived` is a new object each time $effect(() => { derived; }); </script> <button onclick={() => (state.value += 1)}> {state.value} </button> <p>{state.value} doubled is {derived.value}</p> ``` An effect only depends on the values that it read the last time it ran. This has interesting implications for effects that have conditional code. For instance, if `a` is `true` in the code snippet below, the code inside the `if` block will run and `b` will be evaluated. As such, changes to either `a` or `b` [will cause the effect to re-run](/REMOVED). Conversely, if `a` is `false`, `b` will not be evaluated, and the effect will _only_ re-run when `a` changes. ```ts let a = false; let b = false; // ---cut--- $effect(() => { console.log('running'); if (a) { console.log('b:', b); } }); ``` ## `$effect.pre` In rare cases, you may need to run code _before_ the DOM updates. For this we can use the `$effect.pre` rune: ```svelte <script> import { tick } from 'svelte'; let div = $state(); let messages = $state([]); // ... $effect.pre(() => { if (!div) return; // not yet mounted // reference `messages` array length so that this code re-runs whenever it changes messages.length; // autoscroll when new messages are added if (div.offsetHeight + div.scrollTop > div.scrollHeight - 20) { tick().then(() => { div.scrollTo(0, div.scrollHeight); }); } }); </script> <div bind:this={div}> {#each messages as message} <p>{message}</p> {/each} </div> ``` Apart from the timing, `$effect.pre` works exactly like `$effect`. ## `$effect.tracking` The `$effect.tracking` rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template ([demo](/REMOVED)): ```svelte <script> console.log('in component setup:', $effect.tracking()); // false $effect(() => { console.log('in effect:', $effect.tracking()); // true }); </script> <p>in template: {$effect.tracking()}</p> <!-- true --> ``` It is used to implement abstractions like [`createSubscriber`](/docs/svelte/svelte-reactivity#createSubscriber), which will create listeners to update reactive values but _only_ if those values are being tracked (rather than, for example, read inside an event handler). ## `$effect.root` The `$effect.root` rune is an advanced feature that creates a non-tracked scope that doesn't auto-cleanup. This is useful for nested effects that you want to manually control. This rune also allows for the creation of effects outside of the component initialisation phase. ```svelte <script> let count = $state(0); const cleanup = $effect.root(() => { $effect(() => { console.log(count); }); return () => { console.log('effect root cleanup'); }; }); </script> ``` ## When not to use `$effect` In general, `$effect` is best considered something of an escape hatch — useful for things like analytics and direct DOM manipulation — rather than a tool you should use frequently. In particular, avoid using it to synchronise state. Instead of this... ```svelte <script> let count = $state(0); let doubled = $state(); // don't do this! $effect(() => { doubled = count * 2; }); </script> ``` ...do this: ```svelte <script> let count = $state(0); let doubled = $derived(count * 2); </script> ``` You might be tempted to do something convoluted with effects to link one value to another. The following example shows two inputs for "money spent" and "money left" that are connected to each other. If you update one, the other should update accordingly. Don't use effects for this ([demo](/REMOVED)): ```svelte <script> let total = 100; let spent = $state(0); let left = $state(total); $effect(() => { left = total - spent; }); $effect(() => { spent = total - left; }); </script> <label> <input type="range" bind:value={spent} max={total} /> {spent}/{total} spent </label> <label> <input type="range" bind:value={left} max={total} /> {left}/{total} left </label> ``` Instead, use callbacks where possible ([demo](/REMOVED)): ```svelte <script> let total = 100; let spent = $state(0); let left = $state(total); function updateSpent(e) { spent = +e.target.value; left = total - spent; } function updateLeft(e) { left = +e.target.value; spent = total - left; } </script> <label> <input type="range" value={spent} oninput={updateSpent} max={total} /> {spent}/{total} spent </label> <label> <input type="range" value={left} oninput={updateLeft} max={total} /> {left}/{total} left </label> ``` If you need to use bindings, for whatever reason (for example when you want some kind of "writable `$derived`"), consider using getters and setters to synchronise state ([demo](/REMOVED)): ```svelte <script> let total = 100; let spent = $state(0); let left = { get value() { return total - spent; }, set value(v) { spent = total - v; } }; </script> <label> <input type="range" bind:value={spent} max={total} /> {spent}/{total} spent </label> <label> <input type="range" bind:value={left.value} max={total} /> {left.value}/{total} left </label> ``` If you absolutely have to update `$state` within an effect and run into an infinite loop because you read and write to the same `$state`, use [untrack](svelte#untrack).

# $props

The inputs to a component are referred to as _props_, which is short for _properties_. You pass props to components just like you pass attributes to elements: ```svelte <!--- file: App.svelte ---> <script> import MyComponent from './MyComponent.svelte'; </script> <MyComponent adjective="cool" /> ``` On the other side, inside `MyComponent.svelte`, we can receive props with the `$props` rune... ```svelte <!--- file: MyComponent.svelte ---> <script> let props = $props(); </script> <p>this component is {props.adjective}</p> ``` ...though more commonly, you'll [_destructure_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) your props: ```svelte <!--- file: MyComponent.svelte ---> <script> let +++{ adjective }+++ = $props(); </script> <p>this component is {+++adjective+++}</p> ``` ## Fallback values Destructuring allows us to declare fallback values, which are used if the parent component does not set a given prop: ```js let { adjective = 'happy' } = $props(); ``` ## Renaming props We can also use the destructuring assignment to rename props, which is necessary if they're invalid identifiers, or a JavaScript keyword like `super`: ```js let { super: trouper = 'lights are gonna find me' } = $props(); ``` ## Rest props Finally, we can use a _rest property_ to get, well, the rest of the props: ```js let { a, b, c, ...others } = $props(); ``` ## Updating props References to a prop inside a component update when the prop itself updates — when `count` changes in `App.svelte`, it will also change inside `Child.svelte`. But the child component is able to temporarily override the prop value, which can be useful for unsaved ephemeral state ([demo](/REMOVED)): ```svelte <!--- file: App.svelte ---> <script> import Child from './Child.svelte'; let count = $state(0); </script> <button onclick={() => (count += 1)}> clicks (parent): {count} </button> <Child {count} /> ``` ```svelte <!--- file: Child.svelte ---> <script> let { count } = $props(); </script> <button onclick={() => (count += 1)}> clicks (child): {count} </button> ``` While you can temporarily _reassign_ props, you should not _mutate_ props unless they are [bindable]($bindable). If the prop is a regular object, the mutation will have no effect ([demo](/REMOVED)): ```svelte <!--- file: App.svelte ---> <script> import Child from './Child.svelte'; </script> <Child object={{ count: 0 }} /> ``` ```svelte <!--- file: Child.svelte ---> <script> let { object } = $props(); </script> <button onclick={() => { // has no effect object.count += 1 }}> clicks: {object.count} </button> ``` If the prop is a reactive state proxy, however, then mutations _will_ have an effect but you will see an [`ownership_invalid_mutation`](runtime-warnings#Client-warnings-ownership_invalid_mutation) warning, because the component is mutating state that does not 'belong' to it ([demo](/REMOVED)): ```svelte <!--- file: App.svelte ---> <script> import Child from './Child.svelte'; let object = $state({count: 0}); </script> <Child {object} /> ``` ```svelte <!--- file: Child.svelte ---> <script> let { object } = $props(); </script> <button onclick={() => { // will cause the count below to update, // but with a warning. Don't mutate // objects you don't own! object.count += 1 }}> clicks: {object.count} </button> ``` The fallback value of a prop not declared with `$bindable` is left untouched — it is not turned into a reactive state proxy — meaning mutations will not cause updates ([demo](/REMOVED)) ```svelte <!--- file: Child.svelte ---> <script> let { object = { count: 0 } } = $props(); </script> <button onclick={() => { // has no effect if the fallback value is used object.count += 1 }}> clicks: {object.count} </button> ``` In summary: don't mutate props. Either use callback props to communicate changes, or — if parent and child should share the same object — use the [`$bindable`]($bindable) rune. ## Type safety You can add type safety to your components by annotating your props, as you would with any other variable declaration. In TypeScript that might look like this... ```svelte <script lang="ts"> let { adjective }: { adjective: string } = $props(); </script> ``` ...while in JSDoc you can do this: ```svelte <script> /** @type {{ adjective: string }} */ let { adjective } = $props(); </script> ``` You can, of course, separate the type declaration from the annotation: ```svelte <script lang="ts"> interface Props { adjective: string; } let { adjective }: Props = $props(); </script> ``` Adding types is recommended, as it ensures that people using your component can easily discover which props they should provide. ## `$props.id()` This rune, added in version 5.20.0, generates an ID that is unique to the current component instance. When hydrating a server-rendered component, the value will be consistent between server and client. This is useful for linking elements via attributes like `for` and `aria-labelledby`. ```svelte <script> const uid = $props.id(); </script> <form> <label for="{uid}-firstname">First Name: </label> <input id="{uid}-firstname" type="text" /> <label for="{uid}-lastname">Last Name: </label> <input id="{uid}-lastname" type="text" /> </form> ```

# $bindable

Ordinarily, props go one way, from parent to child. This makes it easy to understand how data flows around your app. In Svelte, component props can be _bound_, which means that data can also flow _up_ from child to parent. This isn't something you should do often, but it can simplify your code if used sparingly and carefully. It also means that a state proxy can be _mutated_ in the child. To mark a prop as bindable, we use the `$bindable` rune: ```svelte /// file: FancyInput.svelte <script> let { value = $bindable(), ...props } = $props(); </script> <input bind:value={value} {...props} /> <style> input { font-family: 'Comic Sans MS'; color: deeppink; } </style> ``` Now, a component that uses `<FancyInput>` can add the [`bind:`](bind) directive ([demo](/REMOVED)): ```svelte /// file: App.svelte <script> import FancyInput from './FancyInput.svelte'; let message = $state('hello'); </script> <FancyInput bind:value={message} /> <p>{message}</p> ``` The parent component doesn't _have_ to use `bind:` — it can just pass a normal prop. Some parents don't want to listen to what their children have to say. In this case, you can specify a fallback value for when no prop is passed at all: ```js /// file: FancyInput.svelte let { value = $bindable('fallback'), ...props } = $props(); ```

# $inspect

The `$inspect` rune is roughly equivalent to `console.log`, with the exception that it will re-run whenever its argument changes. `$inspect` tracks reactive state deeply, meaning that updating something inside an object or array using fine-grained reactivity will cause it to re-fire ([demo](/REMOVED)): ```svelte <script> let count = $state(0); let message = $state('hello'); $inspect(count, message); // will console.log when `count` or `message` change </script> <button onclick={() => count++}>Increment</button> <input bind:value={message} /> ``` ## $inspect(...).with `$inspect` returns a property `with`, which you can invoke with a callback, which will then be invoked instead of `console.log`. The first argument to the callback is either `"init"` or `"update"`; subsequent arguments are the values passed to `$inspect` ([demo](/REMOVED)): ```svelte <script> let count = $state(0); $inspect(count).with((type, count) => { if (type === 'update') { debugger; // or `console.trace`, or whatever you want } }); </script> <button onclick={() => count++}>Increment</button> ``` A convenient way to find the origin of some change is to pass `console.trace` to `with`: ```js // @errors: 2304 $inspect(stuff).with(console.trace); ``` ## $inspect.trace(...) This rune, added in 5.14, causes the surrounding function to be _traced_ in development. Any time the function re-runs as part of an [effect]($effect) or a [derived]($derived), information will be printed to the console about which pieces of reactive state caused the effect to fire. ```svelte <script> import { doSomeWork } from './elsewhere'; $effect(() => { +++$inspect.trace();+++ doSomeWork(); }); </script> ``` `$inspect.trace` takes an optional first argument which will be used as the label.

# $host

When compiling a component as a custom element, the `$host` rune provides access to the host element, allowing you to (for example) dispatch custom events ([demo](/REMOVED)): ```svelte /// file: Stepper.svelte <svelte:options customElement="my-stepper" /> <script> function dispatch(type) { +++$host()+++.dispatchEvent(new CustomEvent(type)); } </script> <button onclick={() => dispatch('decrement')}>decrement</button> <button onclick={() => dispatch('increment')}>increment</button> ``` ```svelte /// file: App.svelte <script> import './Stepper.svelte'; let count = $state(0); </script> <my-stepper ondecrement={() => count -= 1} onincrement={() => count += 1} ></my-stepper> <p>count: {count}</p> ```

# Basic markup

Markup inside a Svelte component can be thought of as HTML++. ## Tags A lowercase tag, like `<div>`, denotes a regular HTML element. A capitalised tag or a tag that uses dot notation, such as `<Widget>` or `<my.stuff>`, indicates a _component_. ```svelte <script> import Widget from './Widget.svelte'; </script> <div> <Widget /> </div> ``` ## Element attributes By default, attributes work exactly like their HTML counterparts. ```svelte <div class="foo"> <button disabled>can't touch this</button> </div> ``` As in HTML, values may be unquoted. ```svelte <input type=checkbox /> ``` Attribute values can contain JavaScript expressions. ```svelte <a href="page/{p}">page {p}</a> ``` Or they can _be_ JavaScript expressions. ```svelte <button disabled={!clickable}>...</button> ``` Boolean attributes are included on the element if their value is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) and excluded if it's [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy). All other attributes are included unless their value is [nullish](https://developer.mozilla.org/en-US/docs/Glossary/Nullish) (`null` or `undefined`). ```svelte <input required={false} placeholder="This input field is not required" /> <div title={null}>This div has no title attribute</div> ``` > > <!-- prettier-ignore --> > ```svelte > <button disabled="{number !== 42}">...</button> > ``` When the attribute name and value match (`name={name}`), they can be replaced with `{name}`. ```svelte <button {disabled}>...</button> <!-- equivalent to <button disabled={disabled}>...</button> --> ``` ## Component props By convention, values passed to components are referred to as _properties_ or _props_ rather than _attributes_, which are a feature of the DOM. As with elements, `name={name}` can be replaced with the `{name}` shorthand. ```svelte <Widget foo={bar} answer={42} text="hello" /> ``` _Spread attributes_ allow many attributes or properties to be passed to an element or component at once. An element or component can have multiple spread attributes, interspersed with regular ones. ```svelte <Widget {...things} /> ``` ## Events Listening to DOM events is possible by adding attributes to the element that start with `on`. For example, to listen to the `click` event, add the `onclick` attribute to a button: ```svelte <button onclick={() => console.log('clicked')}>click me</button> ``` Event attributes are case sensitive. `onclick` listens to the `click` event, `onClick` listens to the `Click` event, which is different. This ensures you can listen to custom events that have uppercase characters in them. Because events are just attributes, the same rules as for attributes apply: - you can use the shorthand form: `<button {onclick}>click me</button>` - you can spread them: `<button {...thisSpreadContainsEventAttributes}>click me</button>` Timing-wise, event attributes always fire after events from bindings (e.g. `oninput` always fires after an update to `bind:value`). Under the hood, some event handlers are attached directly with `addEventListener`, while others are _delegated_. When using `ontouchstart` and `ontouchmove` event attributes, the handlers are [passive](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#using_passive_listeners) for better performance. This greatly improves responsiveness by allowing the browser to scroll the document immediately, rather than waiting to see if the event handler calls `event.preventDefault()`. In the very rare cases that you need to prevent these event defaults, you should use [`on`](svelte-events#on) instead (for example inside an action). ### Event delegation To reduce memory footprint and increase performance, Svelte uses a technique called event delegation. This means that for certain events — see the list below — a single event listener at the application root takes responsibility for running any handlers on the event's path. There are a few gotchas to be aware of: - when you manually dispatch an event with a delegated listener, make sure to set the `{ bubbles: true }` option or it won't reach the application root - when using `addEventListener` directly, avoid calling `stopPropagation` or the event won't reach the application root and handlers won't be invoked. Similarly, handlers added manually inside the application root will run _before_ handlers added declaratively deeper in the DOM (with e.g. `onclick={...}`), in both capturing and bubbling phases. For these reasons it's better to use the `on` function imported from `svelte/events` rather than `addEventListener`, as it will ensure that order is preserved and `stopPropagation` is handled correctly. The following event handlers are delegated: - `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 A JavaScript expression can be included as text by surrounding it with curly braces. ```svelte {expression} ``` Curly braces can be included in a Svelte template by using their [HTML entity](https://developer.mozilla.org/docs/Glossary/Entity) strings: `&lbrace;`, `&lcub;`, or `&#123;` for `{` and `&rbrace;`, `&rcub;`, or `&#125;` for `}`. If you're using a regular expression (`RegExp`) [literal notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#literal_notation_and_constructor), you'll need to wrap it in parentheses. ```svelte <h1>Hello {name}!</h1> <p>{a} + {b} = {a + b}.</p> <div>{(/^[A-Za-z ]+$/).test(value) ? x : y}</div> ``` The expression will be stringified and escaped to prevent code injections. If you want to render HTML, use the `{@html}` tag instead. ```svelte {@html potentiallyUnsafeHtmlString} ``` ## Comments You can use HTML comments inside components. ```svelte <!-- this is a comment! --><h1>Hello world</h1> ``` Comments beginning with `svelte-ignore` disable warnings for the next block of markup. Usually, these are accessibility warnings; make sure that you're disabling them for a good reason. ```svelte <!-- svelte-ignore a11y_autofocus --> <input bind:value={name} autofocus /> ``` You can add a special comment starting with `@component` that will show up when hovering over the component name in other files. ````svelte <!-- @component - You can use markdown here. - You can also use code blocks here. - Usage: ```html <Main name="Arethra"> ``` --> <script> let { name } = $props(); </script> <main> <h1> Hello, {name} </h1> </main> ````

# {#if ...}

```svelte <!--- copy: false ---> {#if expression}...{/if} ``` ```svelte <!--- copy: false ---> {#if expression}...{:else if expression}...{/if} ``` ```svelte <!--- copy: false ---> {#if expression}...{:else}...{/if} ``` Content that is conditionally rendered can be wrapped in an if block. ```svelte {#if answer === 42} <p>what was the question?</p> {/if} ``` Additional conditions can be added with `{:else if expression}`, optionally ending in an `{:else}` clause. ```svelte {#if porridge.temperature > 100} <p>too hot!</p> {:else if 80 > porridge.temperature} <p>too cold!</p> {:else} <p>just right!</p> {/if} ``` (Blocks don't have to wrap elements, they can also wrap text within elements.)

# {#each ...}

```svelte <!--- copy: false ---> {#each expression as name}...{/each} ``` ```svelte <!--- copy: false ---> {#each expression as name, index}...{/each} ``` Iterating over values can be done with an each block. The values in question can be arrays, array-like objects (i.e. anything with a `length` property), or iterables like `Map` and `Set` — in other words, anything that can be used with `Array.from`. ```svelte <h1>Shopping list</h1> <ul> {#each items as item} <li>{item.name} x {item.qty}</li> {/each} </ul> ``` An each block can also specify an _index_, equivalent to the second argument in an `array.map(...)` callback: ```svelte {#each items as item, i} <li>{i + 1}: {item.name} x {item.qty}</li> {/each} ``` ## Keyed each blocks ```svelte <!--- copy: false ---> {#each expression as name (key)}...{/each} ``` ```svelte <!--- copy: false ---> {#each expression as name, index (key)}...{/each} ``` If a _key_ expression is provided — which must uniquely identify each list item — Svelte will use it to diff the list when data changes, rather than adding or removing items at the end. The key can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change. ```svelte {#each items as item (item.id)} <li>{item.name} x {item.qty}</li> {/each} <!-- or with additional index value --> {#each items as item, i (item.id)} <li>{i + 1}: {item.name} x {item.qty}</li> {/each} ``` You can freely use destructuring and rest patterns in each blocks. ```svelte {#each items as { id, name, qty }, i (id)} <li>{i + 1}: {name} x {qty}</li> {/each} {#each objects as { id, ...rest }} <li><span>{id}</span><MyComponent {...rest} /></li> {/each} {#each items as [id, ...rest]} <li><span>{id}</span><MyComponent values={rest} /></li> {/each} ``` ## Each blocks without an item ```svelte <!--- copy: false ---> {#each expression}...{/each} ``` ```svelte <!--- copy: false ---> {#each expression, index}...{/each} ``` In case you just want to render something `n` times, you can omit the `as` part ([demo](/REMOVED)): ```svelte <div class="chess-board"> {#each { length: 8 }, rank} {#each { length: 8 }, file} <div class:black={(rank + file) % 2 === 1}></div> {/each} {/each} </div> ``` ## Else blocks ```svelte <!--- copy: false ---> {#each expression as name}...{:else}...{/each} ``` An each block can also have an `{:else}` clause, which is rendered if the list is empty. ```svelte {#each todos as todo} <p>{todo.text}</p> {:else} <p>No tasks today!</p> {/each} ```

# {#key ...}

```svelte <!--- copy: false ---> {#key expression}...{/key} ``` Key blocks destroy and recreate their contents when the value of an expression changes. When used around components, this will cause them to be reinstantiated and reinitialised: ```svelte {#key value} <Component /> {/key} ``` It's also useful if you want a transition to play whenever a value changes: ```svelte {#key value} <div transition:fade>{value}</div> {/key} ```

# {#await ...}

```svelte <!--- copy: false ---> {#await expression}...{:then name}...{:catch name}...{/await} ``` ```svelte <!--- copy: false ---> {#await expression}...{:then name}...{/await} ``` ```svelte <!--- copy: false ---> {#await expression then name}...{/await} ``` ```svelte <!--- copy: false ---> {#await expression catch name}...{/await} ``` Await blocks allow you to branch on the three possible states of a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) — pending, fulfilled or rejected. ```svelte {#await promise} <!-- promise is pending --> <p>waiting for the promise to resolve...</p> {:then value} <!-- promise was fulfilled or not a Promise --> <p>The value is {value}</p> {:catch error} <!-- promise was rejected --> <p>Something went wrong: {error.message}</p> {/await} ``` > > If the provided expression is not a `Promise`, only the `:then` branch will be rendered, including during server-side rendering. The `catch` block can be omitted if you don't need to render anything when the promise rejects (or no error is possible). ```svelte {#await promise} <!-- promise is pending --> <p>waiting for the promise to resolve...</p> {:then value} <!-- promise was fulfilled --> <p>The value is {value}</p> {/await} ``` If you don't care about the pending state, you can also omit the initial block. ```svelte {#await promise then value} <p>The value is {value}</p> {/await} ``` Similarly, if you only want to show the error state, you can omit the `then` block. ```svelte {#await promise catch error} <p>The error is {error}</p> {/await} ``` > > ```svelte > {#await import('./Component.svelte') then { default: Component }} > <Component /> > {/await} > ```

# {#snippet ...}

```svelte <!--- copy: false ---> {#snippet name()}...{/snippet} ``` ```svelte <!--- copy: false ---> {#snippet name(param1, param2, paramN)}...{/snippet} ``` Snippets, and [render tags](@render), are a way to create reusable chunks of markup inside your components. Instead of writing duplicative code like [this](/REMOVED)... ```svelte {#each images as image} {#if image.href} <a href={image.href}> <figure> <img src={image.src} alt={image.caption} width={image.width} height={image.height} /> <figcaption>{image.caption}</figcaption> </figure> </a> {:else} <figure> <img src={image.src} alt={image.caption} width={image.width} height={image.height} /> <figcaption>{image.caption}</figcaption> </figure> {/if} {/each} ``` ...you can write [this](/REMOVED): ```svelte {#snippet figure(image)} <figure> <img src={image.src} alt={image.caption} width={image.width} height={image.height} /> <figcaption>{image.caption}</figcaption> </figure> {/snippet} {#each images as image} {#if image.href} <a href={image.href}> {@render figure(image)} </a> {:else} {@render figure(image)} {/if} {/each} ``` Like function declarations, snippets can have an arbitrary number of parameters, which can have default values, and you can destructure each parameter. You cannot use rest parameters, however. ## Snippet scope Snippets can be declared anywhere inside your component. They can reference values declared outside themselves, for example in the `<script>` tag or in `{#each ...}` blocks ([demo](/REMOVED))... ```svelte <script> let { message = `it's great to see you!` } = $props(); </script> {#snippet hello(name)} <p>hello {name}! {message}!</p> {/snippet} {@render hello('alice')} {@render hello('bob')} ``` ...and they are 'visible' to everything in the same lexical scope (i.e. siblings, and children of those siblings): ```svelte <div> {#snippet x()} {#snippet y()}...{/snippet} <!-- this is fine --> {@render y()} {/snippet} <!-- this will error, as `y` is not in scope --> {@render y()} </div> <!-- this will also error, as `x` is not in scope --> {@render x()} ``` Snippets can reference themselves and each other ([demo](/REMOVED)): ```svelte {#snippet blastoff()} <span>🚀</span> {/snippet} {#snippet countdown(n)} {#if n > 0} <span>{n}...</span> {@render countdown(n - 1)} {:else} {@render blastoff()} {/if} {/snippet} {@render countdown(10)} ``` ## Passing snippets to components Within the template, snippets are values just like any other. As such, they can be passed to components as props ([demo](/REMOVED)): ```svelte <script> import Table from './Table.svelte'; const fruits = [ { name: 'apples', qty: 5, price: 2 }, { name: 'bananas', qty: 10, price: 1 }, { name: 'cherries', qty: 20, price: 0.5 } ]; </script> {#snippet header()} <th>fruit</th> <th>qty</th> <th>price</th> <th>total</th> {/snippet} {#snippet row(d)} <td>{d.name}</td> <td>{d.qty}</td> <td>{d.price}</td> <td>{d.qty * d.price}</td> {/snippet} <Table data={fruits} {header} {row} /> ``` Think about it like passing content instead of data to a component. The concept is similar to slots in web components. As an authoring convenience, snippets declared directly _inside_ a component implicitly become props _on_ the component ([demo](/REMOVED)): ```svelte <!-- this is semantically the same as the above --> <Table data={fruits}> {#snippet header()} <th>fruit</th> <th>qty</th> <th>price</th> <th>total</th> {/snippet} {#snippet row(d)} <td>{d.name}</td> <td>{d.qty}</td> <td>{d.price}</td> <td>{d.qty * d.price}</td> {/snippet} </Table> ``` Any content inside the component tags that is _not_ a snippet declaration implicitly becomes part of the `children` snippet ([demo](/REMOVED)): ```svelte <!--- file: App.svelte ---> <Button>click me</Button> ``` ```svelte <!--- file: Button.svelte ---> <script> let { children } = $props(); </script> <!-- result will be <button>click me</button> --> <button>{@render children()}</button> ``` You can declare snippet props as being optional. You can either use optional chaining to not render anything if the snippet isn't set... ```svelte <script> let { children } = $props(); </script> {@render children?.()} ``` ...or use an `#if` block to render fallback content: ```svelte <script> let { children } = $props(); </script> {#if children} {@render children()} {:else} fallback content {/if} ``` ## Typing snippets Snippets implement the `Snippet` interface imported from `'svelte'`: ```svelte <script lang="ts"> import type { Snippet } from 'svelte'; interface Props { data: any[]; children: Snippet; row: Snippet<[any]>; } let { data, children, row }: Props = $props(); </script> ``` With this change, red squigglies will appear if you try and use the component without providing a `data` prop and a `row` snippet. Notice that the type argument provided to `Snippet` is a tuple, since snippets can have multiple parameters. We can tighten things up further by declaring a generic, so that `data` and `row` refer to the same type: ```svelte <script lang="ts" generics="T"> import type { Snippet } from 'svelte'; let { data, children, row }: { data: T[]; children: Snippet; row: Snippet<[T]>; } = $props(); </script> ``` ## Exporting snippets Snippets declared at the top level of a `.svelte` file can be exported from a `<script module>` for use in other components, provided they don't reference any declarations in a non-module `<script>` (whether directly or indirectly, via other snippets) ([demo](/REMOVED)): ```svelte <script module> export { add }; </script> {#snippet add(a, b)} {a} + {b} = {a + b} {/snippet} ``` > This requires Svelte 5.5.0 or newer ## Programmatic snippets Snippets can be created programmatically with the [`createRawSnippet`](svelte#createRawSnippet) API. This is intended for advanced use cases. ## Snippets and slots In Svelte 4, content can be passed to components using [slots](legacy-slots). Snippets are more powerful and flexible, and as such slots are deprecated in Svelte 5.

# {@render ...}

To render a [snippet](snippet), use a `{@render ...}` tag. ```svelte {#snippet sum(a, b)} <p>{a} + {b} = {a + b}</p> {/snippet} {@render sum(1, 2)} {@render sum(3, 4)} {@render sum(5, 6)} ``` The expression can be an identifier like `sum`, or an arbitrary JavaScript expression: ```svelte {@render (cool ? coolSnippet : lameSnippet)()} ``` ## Optional snippets If the snippet is potentially undefined — for example, because it's an incoming prop — then you can use optional chaining to only render it when it _is_ defined: ```svelte {@render children?.()} ``` Alternatively, use an [`{#if ...}`](if) block with an `:else` clause to render fallback content: ```svelte {#if children} {@render children()} {:else} <p>fallback content</p> {/if} ```

# {@html ...}

To inject raw HTML into your component, use the `{@html ...}` tag: ```svelte <article> {@html content} </article> ``` The expression should be valid standalone HTML — this will not work, because `</div>` is not valid HTML: ```svelte {@html '<div>'}content{@html '</div>'} ``` It also will not compile Svelte code. ## Styling Content rendered this way is 'invisible' to Svelte and as such will not receive [scoped styles](scoped-styles) — in other words, this will not work, and the `a` and `img` styles will be regarded as unused: ```svelte <article> {@html content} </article> <style> article { a { color: hotpink } img { width: 100% } } </style> ``` Instead, use the `:global` modifier to target everything inside the `<article>`: ```svelte <style> article +++:global+++ { a { color: hotpink } img { width: 100% } } </style> ```

# {@const ...}

The `{@const ...}` tag defines a local constant. ```svelte {#each boxes as box} {@const area = box.width * box.height} {box.width} * {box.height} = {area} {/each} ``` `{@const}` is only allowed as an immediate child of a block — `{#if ...}`, `{#each ...}`, `{#snippet ...}` and so on — a `<Component />` or a `<svelte:boundary>`.

# {@debug ...}

The `{@debug ...}` tag offers an alternative to `console.log(...)`. It logs the values of specific variables whenever they change, and pauses code execution if you have devtools open. ```svelte <script> let user = { firstname: 'Ada', lastname: 'Lovelace' }; </script> {@debug user} <h1>Hello {user.firstname}!</h1> ``` `{@debug ...}` accepts a comma-separated list of variable names (not arbitrary expressions). ```svelte <!-- Compiles --> {@debug user} {@debug user1, user2, user3} <!-- WON'T compile --> {@debug user.firstname} {@debug myArray[0]} {@debug !isReady} {@debug typeof user === 'object'} ``` The `{@debug}` tag without any arguments will insert a `debugger` statement that gets triggered when _any_ state changes, as opposed to the specified variables.

# bind:

Data ordinarily flows down, from parent to child. The `bind:` directive allows data to flow the other way, from child to parent. The general syntax is `bind:property={expression}`, where `expression` is an _lvalue_ (i.e. a variable or an object property). When the expression is an identifier with the same name as the property, we can omit the expression — in other words these are equivalent: ```svelte <input bind:value={value} /> <input bind:value /> ``` Svelte creates an event listener that updates the bound value. If an element already has a listener for the same event, that listener will be fired before the bound value is updated. Most bindings are _two-way_, meaning that changes to the value will affect the element and vice versa. A few bindings are _readonly_, meaning that changing their value will have no effect on the element. ## Function bindings You can also use `bind:property={get, set}`, where `get` and `set` are functions, allowing you to perform validation and transformation: ```svelte <input bind:value={ () => value, (v) => value = v.toLowerCase()} /> ``` In the case of readonly bindings like [dimension bindings](#Dimensions), the `get` value should be `null`: ```svelte <div bind:clientWidth={null, redraw} bind:clientHeight={null, redraw} >...</div> ``` > Function bindings are available in Svelte 5.9.0 and newer. ## `<input bind:value>` A `bind:value` directive on an `<input>` element binds the input's `value` property: ```svelte <script> let message = $state('hello'); </script> <input bind:value={message} /> <p>{message}</p> ``` In the case of a numeric input (`type="number"` or `type="range"`), the value will be coerced to a number ([demo](/REMOVED)): ```svelte <script> let a = $state(1); let b = $state(2); </script> <label> <input type="number" bind:value={a} min="0" max="10" /> <input type="range" bind:value={a} min="0" max="10" /> </label> <label> <input type="number" bind:value={b} min="0" max="10" /> <input type="range" bind:value={b} min="0" max="10" /> </label> <p>{a} + {b} = {a + b}</p> ``` If the input is empty or invalid (in the case of `type="number"`), the value is `undefined`. Since 5.6.0, if an `<input>` has a `defaultValue` and is part of a form, it will revert to that value instead of the empty string when the form is reset. Note that for the initial render the value of the binding takes precedence unless it is `null` or `undefined`. ```svelte <script> let value = $state(''); </script> <form> <input bind:value defaultValue="not the empty string"> <input type="reset" value="Reset"> </form> ``` > Use reset buttons sparingly, and ensure that users won't accidentally click them while trying to submit the form. ## `<input bind:checked>` Checkbox and radio inputs can be bound with `bind:checked`: ```svelte <label> <input type="checkbox" bind:checked={accepted} /> Accept terms and conditions </label> ``` Since 5.6.0, if an `<input>` has a `defaultChecked` attribute and is part of a form, it will revert to that value instead of `false` when the form is reset. Note that for the initial render the value of the binding takes precedence unless it is `null` or `undefined`. ```svelte <script> let checked = $state(true); </script> <form> <input type="checkbox" bind:checked defaultChecked={true}> <input type="reset" value="Reset"> </form> ``` ## `<input bind:group>` Inputs that work together can use `bind:group`. ```svelte <script> let tortilla = $state('Plain'); /** @type {Array<string>} */ let fillings = $state([]); </script> <!-- grouped radio inputs are mutually exclusive --> <input type="radio" bind:group={tortilla} value="Plain" /> <input type="radio" bind:group={tortilla} value="Whole wheat" /> <input type="radio" bind:group={tortilla} value="Spinach" /> <!-- grouped checkbox inputs populate an array --> <input type="checkbox" bind:group={fillings} value="Rice" /> <input type="checkbox" bind:group={fillings} value="Beans" /> <input type="checkbox" bind:group={fillings} value="Cheese" /> <input type="checkbox" bind:group={fillings} value="Guac (extra)" /> ``` ## `<input bind:files>` On `<input>` elements with `type="file"`, you can use `bind:files` to get the [`FileList` of selected files](https://developer.mozilla.org/en-US/docs/Web/API/FileList). When you want to update the files programmatically, you always need to use a `FileList` object. Currently `FileList` objects cannot be constructed directly, so you need to create a new [`DataTransfer`](https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer) object and get `files` from there. ```svelte <script> let files = $state(); function clear() { files = new DataTransfer().files; // null or undefined does not work } </script> <label for="avatar">Upload a picture:</label> <input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" /> <button onclick={clear}>clear</button> ``` `FileList` objects also cannot be modified, so if you want to e.g. delete a single file from the list, you need to create a new `DataTransfer` object and add the files you want to keep. ## `<select bind:value>` A `<select>` value binding corresponds to the `value` property on the selected `<option>`, which can be any value (not just strings, as is normally the case in the DOM). ```svelte <select bind:value={selected}> <option value={a}>a</option> <option value={b}>b</option> <option value={c}>c</option> </select> ``` A `<select multiple>` element behaves similarly to a checkbox group. The bound variable is an array with an entry corresponding to the `value` property of each selected `<option>`. ```svelte <select multiple bind:value={fillings}> <option value="Rice">Rice</option> <option value="Beans">Beans</option> <option value="Cheese">Cheese</option> <option value="Guac (extra)">Guac (extra)</option> </select> ``` When the value of an `<option>` matches its text content, the attribute can be omitted. ```svelte <select multiple bind:value={fillings}> <option>Rice</option> <option>Beans</option> <option>Cheese</option> <option>Guac (extra)</option> </select> ``` You can give the `<select>` a default value by adding a `selected` attribute to the`<option>` (or options, in the case of `<select multiple>`) that should be initially selected. If the `<select>` is part of a form, it will revert to that selection when the form is reset. Note that for the initial render the value of the binding takes precedence if it's not `undefined`. ```svelte <select bind:value={selected}> <option value={a}>a</option> <option value={b} selected>b</option> <option value={c}>c</option> </select> ``` ## `<audio>` `<audio>` elements have their own set of bindings — five two-way ones... - [`currentTime`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/currentTime) - [`playbackRate`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/playbackRate) - [`paused`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/paused) - [`volume`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/volume) - [`muted`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/muted) ...and six readonly ones: - [`duration`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/duration) - [`buffered`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/buffered) - [`seekable`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seekable) - [`seeking`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seeking_event) - [`ended`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/ended) - [`readyState`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState) ```svelte <audio src={clip} bind:duration bind:currentTime bind:paused></audio> ``` ## `<video>` `<video>` elements have all the same bindings as [`<audio>`](#audio) elements, plus readonly [`videoWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement/videoWidth) and [`videoHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement/videoHeight) bindings. ## `<img>` `<img>` elements have two readonly bindings: - [`naturalWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalWidth) - [`naturalHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/naturalHeight) ## `<details bind:open>` `<details>` elements support binding to the `open` property. ```svelte <details bind:open={isOpen}> <summary>How do you comfort a JavaScript bug?</summary> <p>You console it.</p> </details> ``` ## Contenteditable bindings Elements with the `contenteditable` attribute support the following bindings: - [`innerHTML`](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML) - [`innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText) - [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) <!-- for some reason puts the comment and html on same line --> ```svelte <div contenteditable="true" bind:innerHTML={html}></div> ``` ## Dimensions All visible elements have the following readonly bindings, measured with a `ResizeObserver`: - [`clientWidth`](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth) - [`clientHeight`](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight) - [`offsetWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth) - [`offsetHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight) ```svelte <div bind:offsetWidth={width} bind:offsetHeight={height}> <Chart {width} {height} /> </div> ``` ## bind:this ```svelte <!--- copy: false ---> bind:this={dom_node} ``` To get a reference to a DOM node, use `bind:this`. The value will be `undefined` until the component is mounted — in other words, you should read it inside an effect or an event handler, but not during component initialisation: ```svelte <script> /** @type {HTMLCanvasElement} */ let canvas; $effect(() => { const ctx = canvas.getContext('2d'); drawStuff(ctx); }); </script> <canvas bind:this={canvas}></canvas> ``` Components also support `bind:this`, allowing you to interact with component instances programmatically. ```svelte <!--- file: App.svelte ---> <ShoppingCart bind:this={cart} /> <button onclick={() => cart.empty()}> Empty shopping cart </button> ``` ```svelte <!--- file: ShoppingCart.svelte ---> <script> // All instance exports are available on the instance object export function empty() { // ... } </script> ``` ## bind:_property_ for components ```svelte bind:property={variable} ``` You can bind to component props using the same syntax as for elements. ```svelte <Keypad bind:value={pin} /> ``` While Svelte props are reactive without binding, that reactivity only flows downward into the component by default. Using `bind:property` allows changes to the property from within the component to flow back up out of the component. To mark a property as bindable, use the [`$bindable`]($bindable) rune: ```svelte <script> let { readonlyProperty, bindableProperty = $bindable() } = $props(); </script> ``` Declaring a property as bindable means it _can_ be used using `bind:`, not that it _must_ be used using `bind:`. Bindable properties can have a fallback value: ```svelte <script> let { bindableProperty = $bindable('fallback value') } = $props(); </script> ``` This fallback value _only_ applies when the property is _not_ bound. When the property is bound and a fallback value is present, the parent is expected to provide a value other than `undefined`, else a runtime error is thrown. This prevents hard-to-reason-about situations where it's unclear which value should apply.

# use:

Actions are functions that are called when an element is mounted. They are added with the `use:` directive, and will typically use an `$effect` so that they can reset any state when the element is unmounted: ```svelte <!--- file: App.svelte ---> <script> /** @type {import('svelte/action').Action} */ function myaction(node) { // the node has been mounted in the DOM $effect(() => { // setup goes here return () => { // teardown goes here }; }); } </script> <div use:myaction>...</div> ``` An action can be called with an argument: ```svelte <!--- file: App.svelte ---> <script> /** @type {import('svelte/action').Action} */ function myaction(node, +++data+++) { // ... } </script> <div use:myaction={+++data+++}>...</div> ``` The action is only called once (but not during server-side rendering) — it will _not_ run again if the argument changes. > Prior to the `$effect` rune, actions could return an object with `update` and `destroy` methods, where `update` would be called with the latest value of the argument if it changed. Using effects is preferred. ## Typing The `Action` interface receives three optional type arguments — a node type (which can be `Element`, if the action applies to everything), a parameter, and any custom event handlers created by the action: ```svelte <!--- file: App.svelte ---> <script> /** * @type {import('svelte/action').Action< * HTMLDivElement, * undefined, * { * onswiperight: (e: CustomEvent) => void; * onswipeleft: (e: CustomEvent) => void; * // ... * } * >} */ function gestures(node) { $effect(() => { // ... node.dispatchEvent(new CustomEvent('swipeleft')); // ... node.dispatchEvent(new CustomEvent('swiperight')); }); } </script> <div use:gestures onswipeleft={next} onswiperight={prev} >...</div> ```

# transition:

A _transition_ is triggered by an element entering or leaving the DOM as a result of a state change. When a block (such as an `{#if ...}` block) is transitioning out, all elements inside it, including those that do not have their own transitions, are kept in the DOM until every transition in the block has been completed. The `transition:` directive indicates a _bidirectional_ transition, which means it can be smoothly reversed while the transition is in progress. ```svelte <script> +++import { fade } from 'svelte/transition';+++ let visible = $state(false); </script> <button onclick={() => visible = !visible}>toggle</button> {#if visible} <div +++transition:fade+++>fades in and out</div> {/if} ``` ## Built-in transitions A selection of built-in transitions can be imported from the [`svelte/transition`](svelte-transition) module. ## Local vs global Transitions are local by default. Local transitions only play when the block they belong to is created or destroyed, _not_ when parent blocks are created or destroyed. ```svelte {#if x} {#if y} <p transition:fade>fades in and out only when y changes</p> <p transition:fade|global>fades in and out when x or y change</p> {/if} {/if} ``` ## Transition parameters Transitions can have parameters. (The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.) ```svelte {#if visible} <div transition:fade={{ duration: 2000 }}>fades in and out over two seconds</div> {/if} ``` ## Custom transition functions ```js /// copy: false // @noErrors 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 } ``` Transitions can use custom functions. If the returned object has a `css` function, Svelte will generate keyframes for a [web animation](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API). The `t` argument passed to `css` is a value between `0` and `1` after the `easing` function has been applied. _In_ transitions run from `0` to `1`, _out_ transitions run from `1` to `0` — in other words, `1` is the element's natural state, as though no transition had been applied. The `u` argument is equal to `1 - t`. The function is called repeatedly _before_ the transition begins, with different `t` and `u` arguments. ```svelte <!--- file: App.svelte ---> <script> import { elasticOut } from 'svelte/easing'; /** @type {boolean} */ export let visible; /** * @param {HTMLElement} node * @param {{ delay?: number, duration?: number, easing?: (t: number) => number }} params */ function whoosh(node, params) { const existingTransform = getComputedStyle(node).transform.replace('none', ''); return { delay: params.delay || 0, duration: params.duration || 400, easing: params.easing || elasticOut, css: (t, u) => `transform: ${existingTransform} scale(${t})` }; } </script> {#if visible} <div in:whoosh>whooshes in</div> {/if} ``` A custom transition function can also return a `tick` function, which is called _during_ the transition with the same `t` and `u` arguments. ```svelte <!--- file: App.svelte ---> <script> export let visible = false; /** * @param {HTMLElement} node * @param {{ speed?: number }} params */ function typewriter(node, { speed = 1 }) { const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE; if (!valid) { throw new Error(`This transition only works on elements with a single text node child`); } const text = node.textContent; const duration = text.length / (speed * 0.01); return { duration, tick: (t) => { const i = ~~(text.length * t); node.textContent = text.slice(0, i); } }; } </script> {#if visible} <p in:typewriter={{ speed: 1 }}>The quick brown fox jumps over the lazy dog</p> {/if} ``` If a transition returns a function instead of a transition object, the function will be called in the next microtask. This allows multiple transitions to coordinate, making [crossfade effects](/tutorial/deferred-transitions) possible. Transition functions also receive a third argument, `options`, which contains information about the transition. Available values in the `options` object are: - `direction` - one of `in`, `out`, or `both` depending on the type of transition ## Transition events An element with transitions will dispatch the following events in addition to any standard DOM events: - `introstart` - `introend` - `outrostart` - `outroend` ```svelte {#if visible} <p transition:fly={{ y: 200, duration: 2000 }} onintrostart={() => (status = 'intro started')} onoutrostart={() => (status = 'outro started')} onintroend={() => (status = 'intro ended')} onoutroend={() => (status = 'outro ended')} > Flies in and out </p> {/if} ```

# in: and out:

The `in:` and `out:` directives are identical to [`transition:`](transition), except that the resulting transitions are not bidirectional — an `in` transition will continue to 'play' alongside the `out` transition, rather than reversing, if the block is outroed while the transition is in progress. If an out transition is aborted, transitions will restart from scratch. ```svelte <script> import { fade, fly } from 'svelte/transition'; let visible = $state(false); </script> <label> <input type="checkbox" bind:checked={visible}> visible </label> {#if visible} <div in:fly={{ y: 200 }} out:fade>flies in, fades out</div> {/if} ```

# animate:

An animation is triggered when the contents of a [keyed each block](each#Keyed-each-blocks) are re-ordered. Animations do not run when an element is added or removed, only when the index of an existing data item within the each block changes. Animate directives must be on an element that is an _immediate_ child of a keyed each block. Animations can be used with Svelte's [built-in animation functions](svelte-animate) or [custom animation functions](#Custom-animation-functions). ```svelte <!-- When `list` is reordered the animation will run --> {#each list as item, index (item)} <li animate:flip>{item}</li> {/each} ``` ## Animation Parameters As with actions and transitions, animations can have parameters. (The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.) ```svelte {#each list as item, index (item)} <li animate:flip={{ delay: 500 }}>{item}</li> {/each} ``` ## Custom animation functions ```js /// copy: false // @noErrors 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 } ``` Animations can use custom functions that provide the `node`, an `animation` object and any `parameters` as arguments. The `animation` parameter is an object containing `from` and `to` properties each containing a [DOMRect](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect#Properties) describing the geometry of the element in its `start` and `end` positions. The `from` property is the DOMRect of the element in its starting position, and the `to` property is the DOMRect of the element in its final position after the list has been reordered and the DOM updated. If the returned object has a `css` method, Svelte will create a [web animation](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API) that plays on the element. The `t` argument passed to `css` is a value that goes from `0` and `1` after the `easing` function has been applied. The `u` argument is equal to `1 - t`. The function is called repeatedly _before_ the animation begins, with different `t` and `u` arguments. <!-- TODO: Types --> ```svelte <!--- file: App.svelte ---> <script> import { cubicOut } from 'svelte/easing'; /** * @param {HTMLElement} node * @param {{ from: DOMRect; to: DOMRect }} states * @param {any} params */ function whizz(node, { from, to }, params) { const dx = from.left - to.left; const dy = from.top - to.top; const d = Math.sqrt(dx * dx + dy * dy); return { delay: 0, duration: Math.sqrt(d) * 120, easing: cubicOut, css: (t, u) => `transform: translate(${u * dx}px, ${u * dy}px) rotate(${t * 360}deg);` }; } </script> {#each list as item, index (item)} <div animate:whizz>{item}</div> {/each} ``` A custom animation function can also return a `tick` function, which is called _during_ the animation with the same `t` and `u` arguments. ```svelte <!--- file: App.svelte ---> <script> import { cubicOut } from 'svelte/easing'; /** * @param {HTMLElement} node * @param {{ from: DOMRect; to: DOMRect }} states * @param {any} params */ function whizz(node, { from, to }, params) { const dx = from.left - to.left; const dy = from.top - to.top; const d = Math.sqrt(dx * dx + dy * dy); return { delay: 0, duration: Math.sqrt(d) * 120, easing: cubicOut, tick: (t, u) => Object.assign(node.style, { color: t > 0.5 ? 'Pink' : 'Blue' }) }; } </script> {#each list as item, index (item)} <div animate:whizz>{item}</div> {/each} ```

# style:

The `style:` directive provides a shorthand for setting multiple styles on an element. ```svelte <!-- These are equivalent --> <div style:color="red">...</div> <div style="color: red;">...</div> ``` The value can contain arbitrary expressions: ```svelte <div style:color={myColor}>...</div> ``` The shorthand form is allowed: ```svelte <div style:color>...</div> ``` Multiple styles can be set on a single element: ```svelte <div style:color style:width="12rem" style:background-color={darkMode ? 'black' : 'white'}>...</div> ``` To mark a style as important, use the `|important` modifier: ```svelte <div style:color|important="red">...</div> ``` When `style:` directives are combined with `style` attributes, the directives will take precedence: ```svelte <div style="color: blue;" style:color="red">This will be red</div> ```

# class

There are two ways to set classes on elements: the `class` attribute, and the `class:` directive. ## Attributes Primitive values are treated like any other attribute: ```svelte <div class={large ? 'large' : 'small'}>...</div> ``` > For historical reasons, falsy values (like `false` and `NaN`) are stringified (`class="false"`), though `class={undefined}` (or `null`) cause the attribute to be omitted altogether. In a future version of Svelte, all falsy values will cause `class` to be omitted. ### Objects and arrays Since Svelte 5.16, `class` can be an object or array, and is converted to a string using [clsx](https://github.com/lukeed/clsx). If the value is an object, the truthy keys are added: ```svelte <script> let { cool } = $props(); </script> <!-- results in `class="cool"` if `cool` is truthy, `class="lame"` otherwise --> <div class={{ cool, lame: !cool }}>...</div> ``` If the value is an array, the truthy values are combined: ```svelte <!-- if `faded` and `large` are both truthy, results in `class="saturate-0 opacity-50 scale-200"` --> <div class={[faded && 'saturate-0 opacity-50', large && 'scale-200']}>...</div> ``` Note that whether we're using the array or object form, we can set multiple classes simultaneously with a single condition, which is particularly useful if you're using things like Tailwind. Arrays can contain arrays and objects, and clsx will flatten them. This is useful for combining local classes with props, for example: ```svelte <!--- file: Button.svelte ---> <script> let props = $props(); </script> <button {...props} class={['cool-button', props.class]}> {@render props.children?.()} </button> ``` The user of this component has the same flexibility to use a mixture of objects, arrays and strings: ```svelte <!--- file: App.svelte ---> <script> import Button from './Button.svelte'; let useTailwind = $state(false); </script> <Button onclick={() => useTailwind = true} class={{ 'bg-blue-700 sm:w-1/2': useTailwind }} > Accept the inevitability of Tailwind </Button> ``` Svelte also exposes the `ClassValue` type, which is the type of value that the `class` attribute on elements accept. This is useful if you want to use a type-safe class name in component props: ```svelte <script lang="ts"> import type { ClassValue } from 'svelte/elements'; const props: { class: ClassValue } = $props(); </script> <div class={['original', props.class]}>...</div> ``` ## The `class:` directive Prior to Svelte 5.16, the `class:` directive was the most convenient way to set classes on elements conditionally. ```svelte <!-- These are equivalent --> <div class={{ cool, lame: !cool }}>...</div> <div class:cool={cool} class:lame={!cool}>...</div> ``` As with other directives, we can use a shorthand when the name of the class coincides with the value: ```svelte <div class:cool class:lame={!cool}>...</div> ```

# Scoped styles

Svelte components can include a `<style>` element containing CSS that belongs to the component. This CSS is _scoped_ by default, meaning that styles will not apply to any elements on the page outside the component in question. This works by adding a class to affected elements, which is based on a hash of the component styles (e.g. `svelte-123xyz`). ```svelte <style> p { /* this will only affect <p> elements in this component */ color: burlywood; } </style> ``` ## Specificity Each scoped selector receives a [specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) increase of 0-1-0, as a result of the scoping class (e.g. `.svelte-123xyz`) being added to the selector. This means that (for example) a `p` selector defined in a component will take precedence over a `p` selector defined in a global stylesheet, even if the global stylesheet is loaded later. In some cases, the scoping class must be added to a selector multiple times, but after the first occurrence it is added with `:where(.svelte-xyz123)` in order to not increase specificity further. ## Scoped keyframes If a component defines `@keyframes`, the name is scoped to the component using the same hashing approach. Any `animation` rules in the component will be similarly adjusted: ```svelte <style> .bouncy { animation: bounce 10s; } /* these keyframes are only accessible inside this component */ @keyframes bounce { /* ... */ } </style> ```

# Global styles

## :global(...) To apply styles to a single selector globally, use the `:global(...)` modifier: ```svelte <style> :global(body) { /* applies to <body> */ margin: 0; } div :global(strong) { /* applies to all <strong> elements, in any component, that are inside <div> elements belonging to this component */ color: goldenrod; } p:global(.big.red) { /* applies to all <p> elements belonging to this component with `class="big red"`, even if it is applied programmatically (for example by a library) */ } </style> ``` If you want to make @keyframes that are accessible globally, you need to prepend your keyframe names with `-global-`. The `-global-` part will be removed when compiled, and the keyframe will then be referenced using just `my-animation-name` elsewhere in your code. ```svelte <style> @keyframes -global-my-animation-name { /* code goes here */ } </style> ``` ## :global To apply styles to a group of selectors globally, create a `:global {...}` block: ```svelte <style> :global { /* applies to every <div> in your application */ div { ... } /* applies to every <p> in your application */ p { ... } } .a :global { /* applies to every `.b .c .d` element, in any component, that is inside an `.a` element in this component */ .b .c .d {...} } </style> ```

# Custom properties

You can pass CSS custom properties — both static and dynamic — to components: ```svelte <Slider bind:value min={0} max={100} --track-color="black" --thumb-color="rgb({r} {g} {b})" /> ``` The above code essentially desugars to this: ```svelte <svelte-css-wrapper style="display: contents; --track-color: black; --thumb-color: rgb({r} {g} {b})"> <Slider bind:value min={0} max={100} /> </svelte-css-wrapper> ``` For an SVG element, it would use `<g>` instead: ```svelte <g style="--track-color: black; --thumb-color: rgb({r} {g} {b})"> <Slider bind:value min={0} max={100} /> </g> ``` Inside the component, we can read these custom properties (and provide fallback values) using [`var(...)`](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties): ```svelte <style> .track { background: var(--track-color, #aaa); } .thumb { background: var(--thumb-color, blue); } </style> ``` You don't _have_ to specify the values directly on the component; as long as the custom properties are defined on a parent element, the component can use them. It's common to define custom properties on the `:root` element in a global stylesheet so that they apply to your entire application.

# Nested <style> elements

There can only be one top-level `<style>` tag per component. However, it is possible to have a `<style>` tag nested inside other elements or logic blocks. In that case, the `<style>` tag will be inserted as-is into the DOM; no scoping or processing will be done on the `<style>` tag. ```svelte <div> <style> /* this style tag will be inserted as-is */ div { /* this will apply to all `<div>` elements in the DOM */ color: red; } </style> </div> ```

# <svelte:boundary>

```svelte <svelte:boundary onerror={handler}>...</svelte:boundary> ``` > This feature was added in 5.3.0 Boundaries allow you to guard against errors in part of your app from breaking the app as a whole, and to recover from those errors. If an error occurs while rendering or updating the children of a `<svelte:boundary>`, or running any [`$effect`]($effect) functions contained therein, the contents will be removed. Errors occurring outside the rendering process (for example, in event handlers or after a `setTimeout` or async work) are _not_ caught by error boundaries. ## Properties For the boundary to do anything, one or both of `failed` and `onerror` must be provided. ### `failed` If a `failed` snippet is provided, it will be rendered with the error that was thrown, and a `reset` function that recreates the contents ([demo](/REMOVED)): ```svelte <svelte:boundary> <FlakyComponent /> {#snippet failed(error, reset)} <button onclick={reset}>oops! try again</button> {/snippet} </svelte:boundary> ``` > As with [snippets passed to components](snippet#Passing-snippets-to-components), the `failed` snippet can be passed explicitly as a property... > > ```svelte > <svelte:boundary {failed}>...</svelte:boundary> > ``` > > ...or implicitly by declaring it directly inside the boundary, as in the example above. ### `onerror` If an `onerror` function is provided, it will be called with the same two `error` and `reset` arguments. This is useful for tracking the error with an error reporting service... ```svelte <svelte:boundary onerror={(e) => report(e)}> ... </svelte:boundary> ``` ...or using `error` and `reset` outside the boundary itself: ```svelte <script> let error = $state(null); let reset = $state(() => {}); function onerror(e, r) { error = e; reset = r; } </script> <svelte:boundary {onerror}> <FlakyComponent /> </svelte:boundary> {#if error} <button onclick={() => { error = null; reset(); }}> oops! try again </button> {/if} ``` If an error occurs inside the `onerror` function (or if you rethrow the error), it will be handled by a parent boundary if such exists.

# <svelte:window>

```svelte <svelte:window onevent={handler} /> ``` ```svelte <svelte:window bind:prop={value} /> ``` The `<svelte:window>` element allows you to add event listeners to the `window` object without worrying about removing them when the component is destroyed, or checking for the existence of `window` when server-side rendering. This element may only appear at the top level of your component — it cannot be inside a block or element. ```svelte <script> function handleKeydown(event) { alert(`pressed the ${event.key} key`); } </script> <svelte:window onkeydown={handleKeydown} /> ``` You can also bind to the following properties: - `innerWidth` - `innerHeight` - `outerWidth` - `outerHeight` - `scrollX` - `scrollY` - `online` — an alias for `window.navigator.onLine` - `devicePixelRatio` All except `scrollX` and `scrollY` are readonly. ```svelte <svelte:window bind:scrollY={y} /> ```

# <svelte:document>

```svelte <svelte:document onevent={handler} /> ``` ```svelte <svelte:document bind:prop={value} /> ``` Similarly to `<svelte:window>`, this element allows you to add listeners to events on `document`, such as `visibilitychange`, which don't fire on `window`. It also lets you use [actions](use) on `document`. As with `<svelte:window>`, this element may only appear the top level of your component and must never be inside a block or element. ```svelte <svelte:document onvisibilitychange={handleVisibilityChange} use:someAction /> ``` You can also bind to the following properties: - `activeElement` - `fullscreenElement` - `pointerLockElement` - `visibilityState` All are readonly.

# <svelte:body>

```svelte <svelte:body onevent={handler} /> ``` Similarly to `<svelte:window>`, this element allows you to add listeners to events on `document.body`, such as `mouseenter` and `mouseleave`, which don't fire on `window`. It also lets you use [actions](use) on the `<body>` element. As with `<svelte:window>` and `<svelte:document>`, this element may only appear the top level of your component and must never be inside a block or element. ```svelte <svelte:body onmouseenter={handleMouseenter} onmouseleave={handleMouseleave} use:someAction /> ```

# <svelte:head>

```svelte <svelte:head>...</svelte:head> ``` This element makes it possible to insert elements into `document.head`. During server-side rendering, `head` content is exposed separately to the main `body` content. As with `<svelte:window>`, `<svelte:document>` and `<svelte:body>`, this element may only appear at the top level of your component and must never be inside a block or element. ```svelte <svelte:head> <title>Hello world!</title> <meta name="description" content="This is where the description goes for SEO" /> </svelte:head> ```

# <svelte:element>

```svelte <svelte:element this={expression} /> ``` The `<svelte:element>` element lets you render an element that is unknown at author time, for example because it comes from a CMS. Any properties and event listeners present will be applied to the element. The only supported binding is `bind:this`, since Svelte's built-in bindings do not work with generic elements. If `this` has a nullish value, the element and its children will not be rendered. If `this` is the name of a [void element](https://developer.mozilla.org/en-US/docs/Glossary/Void_element) (e.g., `br`) and `<svelte:element>` has child elements, a runtime error will be thrown in development mode: ```svelte <script> let tag = $state('hr'); </script> <svelte:element this={tag}> This text cannot appear inside an hr element </svelte:element> ``` Svelte tries its best to infer the correct namespace from the element's surroundings, but it's not always possible. You can make it explicit with an `xmlns` attribute: ```svelte <svelte:element this={tag} xmlns="http://www.w3.org/2000/svg" /> ``` `this` needs to be a valid DOM element tag, things like `#text` or `svelte:head` will not work.

# <svelte:options>

```svelte <svelte:options option={value} /> ``` The `<svelte:options>` element provides a place to specify per-component compiler options, which are detailed in the [compiler section](svelte-compiler#compile). The possible options are: - `runes={true}` — forces a component into _runes mode_ (see the [Legacy APIs](legacy-overview) section) - `runes={false}` — forces a component into _legacy mode_ - `namespace="..."` — the namespace where this component will be used, can be "html" (the default), "svg" or "mathml" - `customElement={...}` — the [options](custom-elements#Component-options) to use when compiling this component as a custom element. If a string is passed, it is used as the `tag` option - `css="injected"` — the component will inject its styles inline: During server side rendering, it's injected as a `<style>` tag in the `head`, during client side rendering, it's loaded via JavaScript > Svelte 4 also included the following options. They are deprecated in Svelte 5 and non-functional in runes mode. > > - `immutable={true}` — you never use mutable data, so the compiler can do simple referential equality checks to determine if values have changed > - `immutable={false}` — the default. Svelte will be more conservative about whether or not mutable objects have changed > - `accessors={true}` — adds getters and setters for the component's props > - `accessors={false}` — the default ```svelte <svelte:options customElement="my-custom-element" /> ```

# Stores

<!-- - how to use - how to write - TODO should the details for the store methods belong to the reference section? --> A _store_ is an object that allows reactive access to a value via a simple _store contract_. The [`svelte/store` module](../svelte-store) contains minimal store implementations which fulfil this contract. Any time you have a reference to a store, you can access its value inside a component by prefixing it with the `$` character. This causes Svelte to declare the prefixed variable, subscribe to the store at component initialisation and unsubscribe when appropriate. Assignments to `$`-prefixed variables require that the variable be a writable store, and will result in a call to the store's `.set` method. Note that the store must be declared at the top level of the component — not inside an `if` block or a function, for example. Local variables (that do not represent store values) must _not_ have a `$` prefix. ```svelte <script> import { writable } from 'svelte/store'; const count = writable(0); console.log($count); // logs 0 count.set(1); console.log($count); // logs 1 $count = 2; console.log($count); // logs 2 </script> ``` ## When to use stores Prior to Svelte 5, stores were the go-to solution for creating cross-component reactive states or extracting logic. With runes, these use cases have greatly diminished. - when extracting logic, it's better to take advantage of runes' universal reactivity: You can use runes outside the top level of components and even place them into JavaScript or TypeScript files (using a `.svelte.js` or `.svelte.ts` file ending) - when creating shared state, you can create a `$state` object containing the values you need and then manipulate said state ```ts /// file: state.svelte.js export const userState = $state({ name: 'name', /* ... */ }); ``` ```svelte <!--- file: App.svelte ---> <script> import { userState } from './state.svelte.js'; </script> <p>User name: {userState.name}</p> <button onclick={() => { userState.name = 'new name'; }}> change name </button> ``` Stores are still a good solution when you have complex asynchronous data streams or it's important to have more manual control over updating values or listening to changes. If you're familiar with RxJs and want to reuse that knowledge, the `$` also comes in handy for you. ## svelte/store The `svelte/store` module contains a minimal store implementation which fulfil the store contract. It provides methods for creating stores that you can update from the outside, stores you can only update from the inside, and for combining and deriving stores. ### `writable` Function that creates a store which has values that can be set from 'outside' components. It gets created as an object with additional `set` and `update` methods. `set` is a method that takes one argument which is the value to be set. The store value gets set to the value of the argument if the store value is not already equal to it. `update` is a method that takes one argument which is a callback. The callback takes the existing store value as its argument and returns the new value to be set to the store. ```js /// file: store.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' ``` If a function is passed as the second argument, it will be called when the number of subscribers goes from zero to one (but not from one to two, etc). That function will be passed a `set` function which changes the value of the store, and an `update` function which works like the `update` method on the store, taking a callback to calculate the store's new value from its old value. It must return a `stop` function that is called when the subscriber count goes from one to zero. ```js /// file: store.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' ``` Note that the value of a `writable` is lost when it is destroyed, for example when the page is refreshed. However, you can write your own logic to sync the value to for example the `localStorage`. ### `readable` Creates a store whose value cannot be set from 'outside', the first argument is the store's initial value, and the second argument to `readable` is the same as the second argument to `writable`. ```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. The callback runs initially when the first subscriber subscribes and then whenever the store dependencies change. In the simplest version, `derived` takes a single store, and the callback returns a derived value. ```ts // @filename: ambient.d.ts import { type Writable } from 'svelte/store'; declare global { const a: Writable<number>; } export {}; // @filename: index.ts // ---cut--- import { derived } from 'svelte/store'; const doubled = derived(a, ($a) => $a * 2); ``` The callback can set a value asynchronously by accepting a second argument, `set`, and an optional third argument, `update`, calling either or both of them when appropriate. In this case, you can also pass a third argument to `derived` — the initial value of the derived store before `set` or `update` is first called. If no initial value is specified, the store's initial value will be `undefined`. ```ts // @filename: ambient.d.ts import { type Writable } from 'svelte/store'; declare global { const a: Writable<number>; } export {}; // @filename: index.ts // @errors: 18046 2769 7006 // ---cut--- 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); // every time $a produces a value, this produces two // values, $a immediately and then $a + 1 a second later }); ``` If you return a function from the callback, it will be called when a) the callback runs again, or b) the last subscriber unsubscribes. ```ts // @filename: ambient.d.ts import { type Writable } from 'svelte/store'; declare global { const frequency: Writable<number>; } export {}; // @filename: index.ts // ---cut--- import { derived } from 'svelte/store'; const tick = derived( frequency, ($frequency, set) => { const interval = setInterval(() => { set(Date.now()); }, 1000 / $frequency); return () => { clearInterval(interval); }; }, 2000 ); ``` In both cases, an array of arguments can be passed as the first argument instead of a single store. ```ts // @filename: ambient.d.ts import { type Writable } from 'svelte/store'; declare global { const a: Writable<number>; const b: Writable<number>; } export {}; // @filename: index.ts // ---cut--- 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` This simple helper function makes a store readonly. You can still subscribe to the changes from the original one using this new readable store. ```js import { readonly, writable } from 'svelte/store'; const writableStore = writable(1); const readableStore = readonly(writableStore); readableStore.subscribe(console.log); writableStore.set(2); // console: 2 // @errors: 2339 readableStore.set(2); // ERROR ``` ### `get` Generally, you should read the value of a store by subscribing to it and using the value as it changes over time. Occasionally, you may need to retrieve the value of a store to which you're not subscribed. `get` allows you to do so. ```ts // @filename: ambient.d.ts import { type Writable } from 'svelte/store'; declare global { const store: Writable<string>; } export {}; // @filename: index.ts // ---cut--- import { get } from 'svelte/store'; const value = get(store); ``` ## Store contract ```ts // @noErrors store = { subscribe: (subscription: (value: any) => void) => (() => void), set?: (value: any) => void } ``` You can create your own stores without relying on [`svelte/store`](../svelte-store), by implementing the _store contract_: 1. A store must contain a `.subscribe` method, which must accept as its argument a subscription function. This subscription function must be immediately and synchronously called with the store's current value upon calling `.subscribe`. All of a store's active subscription functions must later be synchronously called whenever the store's value changes. 2. The `.subscribe` method must return an unsubscribe function. Calling an unsubscribe function must stop its subscription, and its corresponding subscription function must not be called again by the store. 3. A store may _optionally_ contain a `.set` method, which must accept as its argument a new value for the store, and which synchronously calls all of the store's active subscription functions. Such a store is called a _writable store_. For interoperability with RxJS Observables, the `.subscribe` method is also allowed to return an object with an `.unsubscribe` method, rather than return the unsubscription function directly. Note however that unless `.subscribe` synchronously calls the subscription (which is not required by the Observable spec), Svelte will see the value of the store as `undefined` until it does.

# Context

<!-- - get/set/hasContext - how to use, best practises (like encapsulating them) --> Most state is component-level state that lives as long as its component lives. There's also section-wide or app-wide state however, which also needs to be handled somehow. The easiest way to do that is to create global state and just import that. ```ts /// file: state.svelte.js export const myGlobalState = $state({ user: { /* ... */ } /* ... */ }); ``` ```svelte <!--- file: App.svelte ---> <script> import { myGlobalState } from './state.svelte.js'; // ... </script> ``` This has a few drawbacks though: - it only safely works when your global state is only used client-side - for example, when you're building a single page application that does not render any of your components on the server. If your state ends up being managed and updated on the server, it could end up being shared between sessions and/or users, causing bugs - it may give the false impression that certain state is global when in reality it should only used in a certain part of your app To solve these drawbacks, Svelte provides a few `context` primitives which alleviate these problems. ## Setting and getting context To associate an arbitrary object with the current component, use `setContext`. ```svelte <script> import { setContext } from 'svelte'; setContext('key', value); </script> ``` The context is then available to children of the component (including slotted content) with `getContext`. ```svelte <script> import { getContext } from 'svelte'; const value = getContext('key'); </script> ``` `setContext` and `getContext` solve the above problems: - the state is not global, it's scoped to the component. That way it's safe to render your components on the server and not leak state - it's clear that the state is not global but rather scoped to a specific component tree and therefore can't be used in other parts of your app Context is not inherently reactive. If you need reactive values in context then you can pass a `$state` object into context, whose properties _will_ be reactive. ```svelte <!--- file: Parent.svelte ---> <script> import { setContext } from 'svelte'; let value = $state({ count: 0 }); setContext('counter', value); </script> <button onclick={() => value.count++}>increment</button> ``` ```svelte <!--- file: Child.svelte ---> <script> import { getContext } from 'svelte'; const value = getContext('counter'); </script> <p>Count is {value.count}</p> ``` To check whether a given `key` has been set in the context of a parent component, use `hasContext`. ```svelte <script> import { hasContext } from 'svelte'; if (hasContext('key')) { // do something } </script> ``` You can also retrieve the whole context map that belongs to the closest parent component using `getAllContexts`. This is useful, for example, if you programmatically create a component and want to pass the existing context to it. ```svelte <script> import { getAllContexts } from 'svelte'; const contexts = getAllContexts(); </script> ``` ## Encapsulating context interactions The above methods are very unopinionated about how to use them. When your app grows in scale, it's worthwhile to encapsulate setting and getting the context into functions and properly type them. ```ts // @errors: 2304 import { getContext, setContext } from 'svelte'; let userKey = Symbol('user'); export function setUserContext(user: User) { setContext(userKey, user); } export function getUserContext(): User { return getContext(userKey) as User; } ```

# Lifecycle hooks

<!-- - onMount/onDestroy - mention that `$effect` might be better for your use case - beforeUpdate/afterUpdate with deprecation notice? - or skip this entirely and only have it in the reference docs? --> In Svelte 5, the component lifecycle consists of only two parts: Its creation and its destruction. Everything in-between — when certain state is updated — is not related to the component as a whole; only the parts that need to react to the state change are notified. This is because under the hood the smallest unit of change is actually not a component, it's the (render) effects that the component sets up upon component initialization. Consequently, there's no such thing as a "before update"/"after update" hook. ## `onMount` The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. It must be called during the component's initialisation (but doesn't need to live _inside_ the component; it can be called from an external module). `onMount` does not run inside a component that is rendered on the server. ```svelte <script> import { onMount } from 'svelte'; onMount(() => { console.log('the component has mounted'); }); </script> ``` If a function is returned from `onMount`, it will be called when the component is unmounted. ```svelte <script> import { onMount } from 'svelte'; onMount(() => { const interval = setInterval(() => { console.log('beep'); }, 1000); return () => clearInterval(interval); }); </script> ``` ## `onDestroy` Schedules a callback to run immediately before the component is unmounted. Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the only one that runs inside a server-side component. ```svelte <script> import { onDestroy } from 'svelte'; onDestroy(() => { console.log('the component is being destroyed'); }); </script> ``` ## `tick` While there's no "after update" hook, you can use `tick` to ensure that the UI is updated before continuing. `tick` returns a promise that resolves once any pending state changes have been applied, or in the next microtask if there are none. ```svelte <script> import { tick } from 'svelte'; $effect.pre(() => { console.log('the component is about to update'); tick().then(() => { console.log('the component just updated'); }); }); </script> ``` ## Deprecated: `beforeUpdate` / `afterUpdate` Svelte 4 contained hooks that ran before and after the component as a whole was updated. For backwards compatibility, these hooks were shimmed in Svelte 5 but not available inside components that use runes. ```svelte <script> import { beforeUpdate, afterUpdate } from 'svelte'; beforeUpdate(() => { console.log('the component is about to update'); }); afterUpdate(() => { console.log('the component just updated'); }); </script> ``` Instead of `beforeUpdate` use `$effect.pre` and instead of `afterUpdate` use `$effect` instead - these runes offer more granular control and only react to the changes you're actually interested in. ### Chat window example To implement a chat window that autoscrolls to the bottom when new messages appear (but only if you were _already_ scrolled to the bottom), we need to measure the DOM before we update it. In Svelte 4, we do this with `beforeUpdate`, but this is a flawed approach — it fires before _every_ update, whether it's relevant or not. In the example below, we need to introduce checks like `updatingMessages` to make sure we don't mess with the scroll position when someone toggles dark mode. With runes, we can use `$effect.pre`, which behaves the same as `$effect` but runs before the DOM is updated. As long as we explicitly reference `messages` inside the effect body, it will run whenever `messages` changes, but _not_ when `theme` changes. `beforeUpdate`, and its equally troublesome counterpart `afterUpdate`, are therefore deprecated in Svelte 5. - [Before](/REMOVED) - [After](/REMOVED) ```svelte <script> import { ---beforeUpdate, afterUpdate,--- tick } from 'svelte'; ---let updatingMessages = false;--- let theme = +++$state('dark')+++; let messages = +++$state([])+++; let viewport; ---beforeUpdate(() => {--- +++$effect.pre(() => {+++ ---if (!updatingMessages) return;--- +++messages;+++ const autoscroll = viewport && viewport.offsetHeight + viewport.scrollTop > viewport.scrollHeight - 50; if (autoscroll) { tick().then(() => { viewport.scrollTo(0, viewport.scrollHeight); }); } ---updatingMessages = false;--- }); function handleKeydown(event) { if (event.key === 'Enter') { const text = event.target.value; if (!text) return; ---updatingMessages = true;--- messages = [...messages, text]; event.target.value = ''; } } function toggle() { toggleValue = !toggleValue; } </script> <div class:dark={theme === 'dark'}> <div bind:this={viewport}> {#each messages as message} <p>{message}</p> {/each} </div> <input +++onkeydown+++={handleKeydown} /> <button +++onclick+++={toggle}> Toggle dark mode </button> </div> ```

# Imperative component API

<!-- better title needed? - mount - unmount - render - hydrate - how they interact with each other --> Every Svelte application starts by imperatively creating a root component. On the client this component is mounted to a specific element. On the server, you want to get back a string of HTML instead which you can render. The following functions help you achieve those tasks. ## `mount` Instantiates a component and mounts it to the given target: ```js // @errors: 2322 import { mount } from 'svelte'; import App from './App.svelte'; const app = mount(App, { target: document.querySelector('#app'), props: { some: 'property' } }); ``` You can mount multiple components per page, and you can also mount from within your application, for example when creating a tooltip component and attaching it to the hovered element. Note that unlike calling `new App(...)` in Svelte 4, things like effects (including `onMount` callbacks, and action functions) will not run during `mount`. If you need to force pending effects to run (in the context of a test, for example) you can do so with `flushSync()`. ## `unmount` Unmounts a component that was previously created with [`mount`](#mount) or [`hydrate`](#hydrate). If `options.outro` is `true`, [transitions](transition) will play before the component is removed from the DOM: ```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 have completed if `options.outro` is true, or immediately otherwise. ## `render` Only available on the server and when compiling with the `server` option. Takes a component and returns an object with `body` and `head` properties on it, which you can use to populate the HTML when server-rendering your app: ```js // @errors: 2724 2305 2307 import { render } from 'svelte/server'; import App from './App.svelte'; const result = render(App, { props: { some: 'property' } }); result.body; // HTML for somewhere in this <body> tag result.head; // HTML for somewhere in this <head> tag ``` ## `hydrate` Like `mount`, but will reuse up any HTML rendered by Svelte's SSR output (from the [`render`](#render) function) inside the target and make it interactive: ```js // @errors: 2322 import { hydrate } from 'svelte'; import App from './App.svelte'; const app = hydrate(App, { target: document.querySelector('#app'), props: { some: 'property' } }); ``` As with `mount`, effects will not run during `hydrate` — use `flushSync()` immediately afterwards if you need them to.

# Testing

Testing helps you write and maintain your code and guard against regressions. Testing frameworks help you with that, allowing you to describe assertions or expectations about how your code should behave. Svelte is unopinionated about which testing framework you use — you can write unit tests, integration tests, and end-to-end tests using solutions like [Vitest](https://vitest.dev/), [Jasmine](https://jasmine.github.io/), [Cypress](https://www.cypress.io/) and [Playwright](https://playwright.dev/). ## Unit and integration testing using Vitest Unit tests allow you to test small isolated parts of your code. Integration tests allow you to test parts of your application to see if they work together. If you're using Vite (including via SvelteKit), we recommend using [Vitest](https://vitest.dev/). To get started, install Vitest: ```bash npm install -D vitest ``` Then adjust your `vite.config.js`: ```js /// file: vite.config.js import { defineConfig } from +++'vitest/config'+++; export default defineConfig({ // ... // Tell Vitest to use the `browser` entry points in `package.json` files, even though it's running in Node resolve: process.env.VITEST ? { conditions: ['browser'] } : undefined }); ``` You can now write unit tests for code inside your `.js/.ts` files: ```js /// file: 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); }); ``` ```js /// file: multiplier.svelte.js /** * @param {number} initial * @param {number} k */ export function multiplier(initial, k) { let count = $state(initial); return { get value() { return count * k; }, /** @param {number} c */ set: (c) => { count = c; } }; } ``` ### Using runes inside your test files Since Vitest processes your test files the same way as your source files, you can use runes inside your tests as long as the filename includes `.svelte`: ```js /// file: 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); }); ``` ```js /// file: multiplier.svelte.js /** * @param {() => number} getCount * @param {number} k */ export function multiplier(getCount, k) { return { get value() { return getCount() * k; } }; } ``` If the code being tested uses effects, you need to wrap the test inside `$effect.root`: ```js /// file: 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); // logger uses an $effect to log updates of its input let log = logger(() => count); // effects normally run after a microtask, // use flushSync to execute all pending effects synchronously flushSync(); expect(log.value).toEqual([0]); count = 1; flushSync(); expect(log.value).toEqual([0, 1]); }); cleanup(); }); ``` ```js /// file: logger.svelte.js /** * @param {() => any} getValue */ export function logger(getValue) { /** @type {any[]} */ let log = $state([]); $effect(() => { log.push(getValue()); }); return { get value() { return log; } }; } ``` ### Component testing It is possible to test your components in isolation using Vitest. To get started, install jsdom (a library that shims DOM APIs): ```bash npm install -D jsdom ``` Then adjust your `vite.config.js`: ```js /// file: vite.config.js import { defineConfig } from 'vitest/config'; export default defineConfig({ plugins: [ /* ... */ ], test: { // If you are testing components client-side, you need to setup a DOM environment. // If not all your files should have this environment, you can use a // `// @vitest-environment jsdom` comment at the top of the test files instead. environment: 'jsdom' }, // Tell Vitest to use the `browser` entry points in `package.json` files, even though it's running in Node resolve: process.env.VITEST ? { conditions: ['browser'] } : undefined }); ``` After that, you can create a test file in which you import the component to test, interact with it programmatically and write expectations about the results: ```js /// file: component.test.js import { flushSync, mount, unmount } from 'svelte'; import { expect, test } from 'vitest'; import Component from './Component.svelte'; test('Component', () => { // Instantiate the component using Svelte's `mount` API const component = mount(Component, { target: document.body, // `document` exists because of jsdom props: { initial: 0 } }); expect(document.body.innerHTML).toBe('<button>0</button>'); // Click the button, then flush the changes so you can synchronously write expectations document.body.querySelector('button').click(); flushSync(); expect(document.body.innerHTML).toBe('<button>1</button>'); // Remove the component from the DOM unmount(component); }); ``` While the process is very straightforward, it is also low level and somewhat brittle, as the precise structure of your component may change frequently. Tools like [@testing-library/svelte](https://testing-library.com/docs/svelte-testing-library/intro/) can help streamline your tests. The above test could be rewritten like this: ```js /// file: 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); }); ``` When writing component tests that involve two-way bindings, context or snippet props, it's best to create a wrapper component for your specific test and interact with that. `@testing-library/svelte` contains some [examples](https://testing-library.com/docs/svelte-testing-library/example). ## E2E tests using Playwright E2E (short for 'end to end') tests allow you to test your full application through the eyes of the user. This section uses [Playwright](https://playwright.dev/) as an example, but you can also use other solutions like [Cypress](https://www.cypress.io/) or [NightwatchJS](https://nightwatchjs.org/). To get started with Playwright, either install it via [the VS Code extension](https://playwright.dev/docs/getting-started-vscode), or install it from the command line using `npm init playwright`. It is also part of the setup CLI when you run `npx sv create`. After you've done that, you should have a `tests` folder and a Playwright config. You may need to adjust that config to tell Playwright what to do before running the tests - mainly starting your application at a certain port: ```js /// file: 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; ``` You can now start writing tests. These are totally unaware of Svelte as a framework, so you mainly interact with the DOM and write assertions. ```js // @errors: 2307 7031 /// file: 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(); }); ```

# TypeScript

<!-- - [basically what we have today](https://svelte.dev/docs/typescript) - built-in support, but only for type-only features - generics - using `Component` and the other helper types - using `svelte-check` --> You can use TypeScript within Svelte components. IDE extensions like the [Svelte VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) will help you catch errors right in your editor, and [`svelte-check`](https://www.npmjs.com/package/svelte-check) does the same on the command line, which you can integrate into your CI. ## `<script lang="ts">` To use TypeScript inside your Svelte components, add `lang="ts"` to your `script` tags: ```svelte <script lang="ts"> let name: string = 'world'; function greet(name: string) { alert(`Hello, ${name}!`); } </script> <button onclick={(e: Event) => greet(e.target.innerText)}> {name as string} </button> ``` Doing so allows you to use TypeScript's _type-only_ features. That is, all features that just disappear when transpiling to JavaScript, such as type annotations or interface declarations. Features that require the TypeScript compiler to output actual code are not supported. This includes: - using enums - using `private`, `protected` or `public` modifiers in constructor functions together with initializers - using features that are not yet part of the ECMAScript standard (i.e. not level 4 in the TC39 process) and therefore not implemented yet within Acorn, the parser we use for parsing JavaScript If you want to use one of these features, you need to setup up a `script` preprocessor. ## Preprocessor setup To use non-type-only TypeScript features within Svelte components, you need to add a preprocessor that will turn TypeScript into JavaScript. ```ts /// file: svelte.config.js // @noErrors import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; const config = { // Note the additional `{ script: true }` preprocess: vitePreprocess({ script: true }) }; export default config; ``` ### Using SvelteKit or Vite The easiest way to get started is scaffolding a new SvelteKit project by typing `npx sv create`, following the prompts and choosing the TypeScript option. ```ts /// file: svelte.config.js // @noErrors import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; const config = { preprocess: vitePreprocess() }; export default config; ``` If you don't need or want all the features SvelteKit has to offer, you can scaffold a Svelte-flavoured Vite project instead by typing `npm create vite@latest` and selecting the `svelte-ts` option. In both cases, a `svelte.config.js` with `vitePreprocess` will be added. Vite/SvelteKit will read from this config file. ### Other build tools If you're using tools like Rollup or Webpack instead, install their respective Svelte plugins. For Rollup that's [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) and for Webpack that's [svelte-loader](https://github.com/sveltejs/svelte-loader). For both, you need to install `typescript` and `svelte-preprocess` and add the preprocessor to the plugin config (see the respective READMEs for more info). If you're starting a new project, you can also use the [rollup](https://github.com/sveltejs/template) or [webpack](https://github.com/sveltejs/template-webpack) template to scaffold the setup from a script. ## tsconfig.json settings When using TypeScript, make sure your `tsconfig.json` is setup correctly. - Use a [`target`](https://www.typescriptlang.org/tsconfig/#target) of at least `ES2022`, or a `target` of at least `ES2015` alongside [`useDefineForClassFields`](https://www.typescriptlang.org/tsconfig/#useDefineForClassFields). This ensures that rune declarations on class fields are not messed with, which would break the Svelte compiler - Set [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) to `true` so that imports are left as-is - Set [`isolatedModules`](https://www.typescriptlang.org/tsconfig/#isolatedModules) to `true` so that each file is looked at in isolation. TypeScript has a few features which require cross-file analysis and compilation, which the Svelte compiler and tooling like Vite don't do. ## Typing `$props` Type `$props` just like a regular object with certain properties. ```svelte <script lang="ts"> import type { Snippet } from 'svelte'; interface Props { requiredProperty: number; optionalProperty?: boolean; snippetWithStringArgument: Snippet<[string]>; eventHandler: (arg: string) => void; [key: string]: unknown; } let { requiredProperty, optionalProperty, snippetWithStringArgument, eventHandler, ...everythingElse }: Props = $props(); </script> <button onclick={() => eventHandler('clicked button')}> {@render snippetWithStringArgument('hello')} </button> ``` ## Generic `$props` Components can declare a generic relationship between their properties. One example is a generic list component that receives a list of items and a callback property that receives an item from the list. To declare that the `items` property and the `select` callback operate on the same types, add the `generics` attribute to the `script` tag: ```svelte <script lang="ts" generics="Item extends { text: string }"> interface Props { items: Item[]; select(item: Item): void; } let { items, select }: Props = $props(); </script> {#each items as item} <button onclick={() => select(item)}> {item.text} </button> {/each} ``` The content of `generics` is what you would put between the `<...>` tags of a generic function. In other words, you can use multiple generics, `extends` and fallback types. ## Typing wrapper components In case you're writing a component that wraps a native element, you may want to expose all the attributes of the underlying element to the user. In that case, use (or extend from) one of the interfaces provided by `svelte/elements`. Here's an example for a `Button` component: ```svelte <script lang="ts"> import type { HTMLButtonAttributes } from 'svelte/elements'; let { children, ...rest }: HTMLButtonAttributes = $props(); </script> <button {...rest}> {@render children?.()} </button> ``` Not all elements have a dedicated type definition. For those without one, use `SvelteHTMLElements`: ```svelte <script lang="ts"> import type { SvelteHTMLElements } from 'svelte/elements'; let { children, ...rest }: SvelteHTMLElements['div'] = $props(); </script> <div {...rest}> {@render children?.()} </div> ``` ## Typing `$state` You can type `$state` like any other variable. ```ts let count: number = $state(0); ``` If you don't give `$state` an initial value, part of its types will be `undefined`. ```ts // @noErrors // Error: Type 'number | undefined' is not assignable to type 'number' let count: number = $state(); ``` If you know that the variable _will_ be defined before you first use it, use an `as` casting. This is especially useful in the context of classes: ```ts class Counter { count = $state() as number; constructor(initial: number) { this.count = initial; } } ``` ## The `Component` type Svelte components are of type `Component`. You can use it and its related types to express a variety of constraints. Using it together with dynamic components to restrict what kinds of component can be passed to it: ```svelte <script lang="ts"> import type { Component } from 'svelte'; interface Props { // only components that have at most the "prop" // property required can be passed DynamicComponent: Component<{ prop: string }>; } let { DynamicComponent }: Props = $props(); </script> <DynamicComponent prop="foo" /> ``` To extract the properties from a component, use `ComponentProps`. ```ts import type { Component, ComponentProps } from 'svelte'; import MyComponent from './MyComponent.svelte'; function withProps<TComponent extends Component<any>>( component: TComponent, props: ComponentProps<TComponent> ) {} // Errors if the second argument is not the correct props expected // by the component in the first argument. withProps(MyComponent, { foo: 'bar' }); ``` To declare that a variable expects the constructor or instance type of a component: ```svelte <script lang="ts"> import MyComponent from './MyComponent.svelte'; let componentConstructor: typeof MyComponent = MyComponent; let componentInstance: MyComponent; </script> <MyComponent bind:this={componentInstance} /> ``` ## Enhancing built-in DOM types Svelte provides a best effort of all the HTML DOM types that exist. Sometimes you may want to use experimental attributes or custom events coming from an action. In these cases, TypeScript will throw a type error, saying that it does not know these types. If it's a non-experimental standard attribute/event, this may very well be a missing typing from our [HTML typings](https://github.com/sveltejs/svelte/blob/main/packages/svelte/elements.d.ts). In that case, you are welcome to open an issue and/or a PR fixing it. In case this is a custom or experimental attribute/event, you can enhance the typings like this: ```ts /// file: additional-svelte-typings.d.ts declare namespace svelteHTML { // enhance elements interface IntrinsicElements { 'my-custom-element': { someattribute: string; 'on:event': (e: CustomEvent<any>) => void }; } // enhance attributes interface HTMLAttributes<T> { // If you want to use the beforeinstallprompt event onbeforeinstallprompt?: (event: any) => any; // If you want to use myCustomAttribute={..} (note: all lowercase) mycustomattribute?: any; // You can replace any with something more specific if you like } } ``` Then make sure that `d.ts` file is referenced in your `tsconfig.json`. If it reads something like `"include": ["src/**/*"]` and your `d.ts` file is inside `src`, it should work. You may need to reload for the changes to take effect. You can also declare the typings by augmenting the `svelte/elements` module like this: ```ts /// file: additional-svelte-typings.d.ts import { HTMLButtonAttributes } from 'svelte/elements'; declare module 'svelte/elements' { export interface SvelteHTMLElements { 'custom-button': HTMLButtonAttributes; } // allows for more granular control over what element to add the typings to export interface HTMLButtonAttributes { veryexperimentalattribute?: string; } } export {}; // ensure this is not an ambient module, else types will be overridden instead of augmented ```

# svelte

```js // @noErrors import { SvelteComponent, SvelteComponentTyped, afterUpdate, beforeUpdate, createEventDispatcher, createRawSnippet, flushSync, getAllContexts, getContext, hasContext, hydrate, mount, onDestroy, onMount, setContext, tick, unmount, untrack } from 'svelte'; ``` ## SvelteComponent This was the base class for Svelte components in Svelte 4. Svelte 5+ components are completely different under the hood. For typing, use `Component` instead. To instantiate components, use `mount` instead. See [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) for more info. <div class="ts-block"> ```dts class SvelteComponent< Props extends Record<string, any> = Record<string, any>, Events extends Record<string, any> = any, Slots extends Record<string, any> = any > {/*…*/} ``` <div class="ts-block-property"> ```dts static element?: typeof HTMLElement; ``` <div class="ts-block-property-details"> The custom element version of the component. Only present if compiled with the `customElement` compiler option </div> </div> <div class="ts-block-property"> ```dts [prop: string]: any; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts constructor(options: ComponentConstructorOptions<Properties<Props, Slots>>); ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> This constructor only exists when using the `asClassComponent` compatibility helper, which is a stop-gap solution. Migrate towards using `mount` instead. See [migration guide](https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) for more info. </div> </div> </div> <div class="ts-block-property"> ```dts $destroy(): void; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> This method only exists when using one of the legacy compatibility helpers, which is a stop-gap solution. See [migration guide](https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) for more info. </div> </div> </div> <div class="ts-block-property"> ```dts $on<K extends Extract<keyof Events, string>>( type: K, callback: (e: Events[K]) => void ): () => void; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> This method only exists when using one of the legacy compatibility helpers, which is a stop-gap solution. See [migration guide](https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) for more info. </div> </div> </div> <div class="ts-block-property"> ```dts $set(props: Partial<Props>): void; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> This method only exists when using one of the legacy compatibility helpers, which is a stop-gap solution. See [migration guide](https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) for more info. </div> </div> </div></div> ## SvelteComponentTyped <blockquote class="tag deprecated note"> Use `Component` instead. See [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) for more information. </blockquote> <div class="ts-block"> ```dts class SvelteComponentTyped< Props extends Record<string, any> = Record<string, any>, Events extends Record<string, any> = any, Slots extends Record<string, any> = any > extends SvelteComponent<Props, Events, Slots> {} ``` </div> ## afterUpdate <blockquote class="tag deprecated note"> Use [`$effect`](/docs/svelte/$effect) instead </blockquote> Schedules a callback to run immediately after the component has been updated. The first time the callback runs will be after the initial `onMount`. In runes mode use `$effect` instead. <div class="ts-block"> ```dts function afterUpdate(fn: () => void): void; ``` </div> ## beforeUpdate <blockquote class="tag deprecated note"> Use [`$effect.pre`](/docs/svelte/$effect#$effect.pre) instead </blockquote> Schedules a callback to run immediately before the component is updated after any state change. The first time the callback runs will be before the initial `onMount`. In runes mode use `$effect.pre` instead. <div class="ts-block"> ```dts function beforeUpdate(fn: () => void): void; ``` </div> ## createEventDispatcher <blockquote class="tag deprecated note"> Use callback props and/or the `$host()` rune instead — see [migration guide](/docs/svelte/v5-migration-guide#Event-changes-Component-events) </blockquote> Creates an event dispatcher that can be used to dispatch [component events](/docs/svelte/legacy-on#Component-events). Event dispatchers are functions that can take two arguments: `name` and `detail`. Component events created with `createEventDispatcher` create a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture). The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) property and can contain any type of data. The event dispatcher can be typed to narrow the allowed event names and the type of the `detail` argument: ```ts const dispatch = createEventDispatcher<{ loaded: never; // does not take a detail argument change: string; // takes a detail argument of type string, which is required optional: number | null; // takes an optional detail argument of type number }>(); ``` <div class="ts-block"> ```dts function createEventDispatcher< EventMap extends Record<string, any> = any >(): EventDispatcher<EventMap>; ``` </div> ## createRawSnippet Create a snippet programmatically <div class="ts-block"> ```dts function createRawSnippet<Params extends unknown[]>( fn: (...params: Getters<Params>) => { render: () => string; setup?: (element: Element) => void | (() => void); } ): Snippet<Params>; ``` </div> ## flushSync Synchronously flush any pending updates. Returns void if no callback is provided, otherwise returns the result of calling the callback. <div class="ts-block"> ```dts function flushSync<T = void>(fn?: (() => T) | undefined): T; ``` </div> ## getAllContexts Retrieves the whole context map that belongs to the closest parent component. Must be called during component initialisation. Useful, for example, if you programmatically create a component and want to pass the existing context to it. <div class="ts-block"> ```dts function getAllContexts< T extends Map<any, any> = Map<any, any> >(): T; ``` </div> ## getContext Retrieves the context that belongs to the closest parent component with the specified `key`. Must be called during component initialisation. <div class="ts-block"> ```dts function getContext<T>(key: any): T; ``` </div> ## hasContext Checks whether a given `key` has been set in the context of a parent component. Must be called during component initialisation. <div class="ts-block"> ```dts function hasContext(key: any): boolean; ``` </div> ## hydrate Hydrates a component on the given target and returns the exports and potentially the props (if compiled with `accessors: true`) of the component <div class="ts-block"> ```dts function hydrate< Props extends Record<string, any>, Exports extends Record<string, any> >( component: | ComponentType<SvelteComponent<Props>> | Component<Props, Exports, any>, options: {} extends Props ? { target: Document | Element | ShadowRoot; props?: Props; events?: Record<string, (e: any) => any>; context?: Map<any, any>; intro?: boolean; recover?: boolean; } : { target: Document | Element | ShadowRoot; props: Props; events?: Record<string, (e: any) => any>; context?: Map<any, any>; intro?: boolean; recover?: boolean; } ): Exports; ``` </div> ## mount Mounts a component to the given target and returns the exports and potentially the props (if compiled with `accessors: true`) of the component. Transitions will play during the initial render unless the `intro` option is set to `false`. <div class="ts-block"> ```dts function mount< Props extends Record<string, any>, Exports extends Record<string, any> >( component: | ComponentType<SvelteComponent<Props>> | Component<Props, Exports, any>, options: MountOptions<Props> ): Exports; ``` </div> ## onDestroy Schedules a callback to run immediately before the component is unmounted. Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the only one that runs inside a server-side component. <div class="ts-block"> ```dts function onDestroy(fn: () => any): void; ``` </div> ## onMount The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. It must be called during the component's initialisation (but doesn't need to live *inside* the component; it can be called from an external module). If a function is returned _synchronously_ from `onMount`, it will be called when the component is unmounted. `onMount` does not run inside [server-side components](/docs/svelte/svelte-server#render). <div class="ts-block"> ```dts function onMount<T>( fn: () => | NotFunction<T> | Promise<NotFunction<T>> | (() => any) ): void; ``` </div> ## setContext Associates an arbitrary `context` object with the current component and the specified `key` and returns that object. The context is then available to children of the component (including slotted content) with `getContext`. Like lifecycle functions, this must be called during component initialisation. <div class="ts-block"> ```dts function setContext<T>(key: any, context: T): T; ``` </div> ## tick Returns a promise that resolves once any pending state changes have been applied. <div class="ts-block"> ```dts function tick(): Promise<void>; ``` </div> ## unmount Unmounts a component that was previously mounted using `mount` or `hydrate`. Since 5.13.0, if `options.outro` is `true`, [transitions](/docs/svelte/transition) will play before the component is removed from the DOM. Returns a `Promise` that resolves after transitions have completed if `options.outro` is true, or immediately otherwise (prior to 5.13.0, returns `void`). ```js // @errors: 7031 import { mount, unmount } from 'svelte'; import App from './App.svelte'; const app = mount(App, { target: document.body }); // later... unmount(app, { outro: true }); ``` <div class="ts-block"> ```dts function unmount( component: Record<string, any>, options?: | { outro?: boolean; } | undefined ): Promise<void>; ``` </div> ## untrack When used inside a [`$derived`](/docs/svelte/$derived) or [`$effect`](/docs/svelte/$effect), any state read inside `fn` will not be treated as a dependency. ```ts $effect(() => { // this will run when `data` changes, but not when `time` changes save(data, { timestamp: untrack(() => time) }); }); ``` <div class="ts-block"> ```dts function untrack<T>(fn: () => T): T; ``` </div> ## Component Can be used to create strongly typed Svelte components. #### Example: You have component library on npm called `component-library`, from which you export a component called `MyComponent`. For Svelte+TypeScript users, you want to provide typings. Therefore you create a `index.d.ts`: ```ts import type { Component } from 'svelte'; export declare const MyComponent: Component<{ foo: string }> {} ``` Typing this makes it possible for IDEs like VS Code with the Svelte extension to provide intellisense and to use the component like this in a Svelte file with TypeScript: ```svelte <script lang="ts"> import { MyComponent } from "component-library"; </script> <MyComponent foo={'bar'} /> ``` <div class="ts-block"> ```dts interface Component< Props extends Record<string, any> = {}, Exports extends Record<string, any> = {}, Bindings extends keyof Props | '' = string > {/*…*/} ``` <div class="ts-block-property"> ```dts ( this: void, internals: ComponentInternals, props: Props ): { /** * @deprecated This method only exists when using one of the legacy compatibility helpers, which * is a stop-gap solution. See [migration guide](https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) * for more info. */ $on?(type: string, callback: (e: any) => void): () => void; /** * @deprecated This method only exists when using one of the legacy compatibility helpers, which * is a stop-gap solution. See [migration guide](https://svelte.dev/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) * for more info. */ $set?(props: Partial<Props>): void; } & Exports; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `internal` An internal object used by Svelte. Do not use or modify. - `props` The props passed to the component. </div> </div> </div> <div class="ts-block-property"> ```dts element?: typeof HTMLElement; ``` <div class="ts-block-property-details"> The custom element version of the component. Only present if compiled with the `customElement` compiler option </div> </div></div> ## ComponentConstructorOptions <blockquote class="tag deprecated note"> In Svelte 4, components are classes. In Svelte 5, they are functions. Use `mount` instead to instantiate components. See [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-longer-classes) for more info. </blockquote> <div class="ts-block"> ```dts interface ComponentConstructorOptions< Props extends Record<string, any> = Record<string, any> > {/*…*/} ``` <div class="ts-block-property"> ```dts target: Element | Document | ShadowRoot; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts anchor?: Element; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts props?: Props; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts context?: Map<any, any>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts hydrate?: boolean; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts intro?: boolean; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts recover?: boolean; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts sync?: boolean; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts idPrefix?: string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts $$inline?: boolean; ``` <div class="ts-block-property-details"></div> </div></div> ## ComponentEvents <blockquote class="tag deprecated note"> The new `Component` type does not have a dedicated Events type. Use `ComponentProps` instead. </blockquote> <div class="ts-block"> ```dts type ComponentEvents<Comp extends SvelteComponent> = Comp extends SvelteComponent<any, infer Events> ? Events : never; ``` </div> ## ComponentInternals Internal implementation details that vary between environments <div class="ts-block"> ```dts type ComponentInternals = Branded<{}, 'ComponentInternals'>; ``` </div> ## ComponentProps Convenience type to get the props the given component expects. Example: Ensure a variable contains the props expected by `MyComponent`: ```ts import type { ComponentProps } from 'svelte'; import MyComponent from './MyComponent.svelte'; // Errors if these aren't the correct props expected by MyComponent. const props: ComponentProps<typeof MyComponent> = { foo: 'bar' }; ``` Example: A generic function that accepts some component and infers the type of its props: ```ts import type { Component, ComponentProps } from 'svelte'; import MyComponent from './MyComponent.svelte'; function withProps<TComponent extends Component<any>>( component: TComponent, props: ComponentProps<TComponent> ) {}; // Errors if the second argument is not the correct props expected by the component in the first argument. withProps(MyComponent, { foo: 'bar' }); ``` <div class="ts-block"> ```dts type ComponentProps< Comp extends SvelteComponent | Component<any, any> > = Comp extends SvelteComponent<infer Props> ? Props : Comp extends Component<infer Props, any> ? Props : never; ``` </div> ## ComponentType <blockquote class="tag deprecated note"> This type is obsolete when working with the new `Component` type. </blockquote> <div class="ts-block"> ```dts type ComponentType< Comp extends SvelteComponent = SvelteComponent > = (new ( options: ComponentConstructorOptions< Comp extends SvelteComponent<infer Props> ? Props : Record<string, any> > ) => Comp) & { /** The custom element version of the component. Only present if compiled with the `customElement` compiler option */ element?: typeof HTMLElement; }; ``` </div> ## EventDispatcher <div class="ts-block"> ```dts interface EventDispatcher< EventMap extends Record<string, any> > {/*…*/} ``` <div class="ts-block-property"> ```dts <Type extends keyof EventMap>( ...args: null extends EventMap[Type] ? [type: Type, parameter?: EventMap[Type] | null | undefined, options?: DispatchOptions] : undefined extends EventMap[Type] ? [type: Type, parameter?: EventMap[Type] | null | undefined, options?: DispatchOptions] : [type: Type, parameter: EventMap[Type], options?: DispatchOptions] ): boolean; ``` <div class="ts-block-property-details"></div> </div></div> ## MountOptions Defines the options accepted by the `mount()` function. <div class="ts-block"> ```dts type MountOptions< Props extends Record<string, any> = Record<string, any> > = { /** * Target element where the component will be mounted. */ target: Document | Element | ShadowRoot; /** * Optional node inside `target`. When specified, it is used to render the component immediately before it. */ anchor?: Node; /** * Allows the specification of events. * @deprecated Use callback props instead. */ events?: Record<string, (e: any) => any>; /** * Can be accessed via `getContext()` at the component level. */ context?: Map<any, any>; /** * Whether or not to play transitions on initial render. * @default true */ intro?: boolean; } & ({} extends Props ? { /** * Component properties. */ props?: Props; } : { /** * Component properties. */ props: Props; }); ``` </div> ## Snippet The type of a `#snippet` block. You can use it to (for example) express that your component expects a snippet of a certain type: ```ts let { banner }: { banner: Snippet<[{ text: string }]> } = $props(); ``` You can only call a snippet through the `{@render ...}` tag. See the [snippet documentation](/docs/svelte/snippet) for more info. <div class="ts-block"> ```dts interface Snippet<Parameters extends unknown[] = []> {/*…*/} ``` <div class="ts-block-property"> ```dts ( this: void, // this conditional allows tuples but not arrays. Arrays would indicate a // rest parameter type, which is not supported. If rest parameters are added // in the future, the condition can be removed. ...args: number extends Parameters['length'] ? never : Parameters ): { '{@render ...} must be called with a Snippet': "import type { Snippet } from 'svelte'"; } & typeof SnippetReturn; ``` <div class="ts-block-property-details"></div> </div></div>

# svelte/action

## Action Actions are functions that are called when an element is created. You can use this interface to type such actions. The following example defines an action that only works on `<div>` elements and optionally accepts a parameter which it has a default value for: ```ts export const myAction: Action<HTMLDivElement, { someProperty: boolean } | undefined> = (node, param = { someProperty: true }) => { // ... } ``` `Action<HTMLDivElement>` and `Action<HTMLDivElement, undefined>` both signal that the action accepts no parameters. You can return an object with methods `update` and `destroy` from the function and type which additional attributes and events it has. See interface `ActionReturn` for more details. <div class="ts-block"> ```dts interface Action< Element = HTMLElement, Parameter = undefined, Attributes extends Record<string, any> = Record< never, any > > {/*…*/} ``` <div class="ts-block-property"> ```dts <Node extends Element>( ...args: undefined extends Parameter ? [node: Node, parameter?: Parameter] : [node: Node, parameter: Parameter] ): void | ActionReturn<Parameter, Attributes>; ``` <div class="ts-block-property-details"></div> </div></div> ## ActionReturn Actions can return an object containing the two properties defined in this interface. Both are optional. - update: An action can have a parameter. This method will be called whenever that parameter changes, immediately after Svelte has applied updates to the markup. `ActionReturn` and `ActionReturn<undefined>` both mean that the action accepts no parameters. - destroy: Method that is called after the element is unmounted Additionally, you can specify which additional attributes and events the action enables on the applied element. This applies to TypeScript typings only and has no effect at runtime. Example usage: ```ts interface Attributes { newprop?: string; 'on:event': (e: CustomEvent<boolean>) => void; } export function myAction(node: HTMLElement, parameter: Parameter): ActionReturn<Parameter, Attributes> { // ... return { update: (updatedParameter) => {...}, destroy: () => {...} }; } ``` <div class="ts-block"> ```dts interface ActionReturn< Parameter = undefined, Attributes extends Record<string, any> = Record< never, any > > {/*…*/} ``` <div class="ts-block-property"> ```dts update?: (parameter: Parameter) => void; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts destroy?: () => void; ``` <div class="ts-block-property-details"></div> </div></div>

# svelte/animate

```js // @noErrors import { flip } from 'svelte/animate'; ``` ## flip The flip function calculates the start and end position of an element and animates between them, translating the x and y values. `flip` stands for [First, Last, Invert, Play](https://aerotwist.com/blog/flip-your-animations/). <div class="ts-block"> ```dts function flip( node: Element, { from, to }: { from: DOMRect; to: DOMRect; }, params?: FlipParams ): AnimationConfig; ``` </div> ## AnimationConfig <div class="ts-block"> ```dts interface AnimationConfig {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: (t: number) => number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts css?: (t: number, u: number) => string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts tick?: (t: number, u: number) => void; ``` <div class="ts-block-property-details"></div> </div></div> ## FlipParams <div class="ts-block"> ```dts interface FlipParams {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number | ((len: number) => number); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: (t: number) => number; ``` <div class="ts-block-property-details"></div> </div></div>

# svelte/compiler

```js // @noErrors import { VERSION, compile, compileModule, migrate, parse, preprocess, walk } from 'svelte/compiler'; ``` ## VERSION The current version, as set in package.json. <div class="ts-block"> ```dts const VERSION: string; ``` </div> ## compile `compile` converts your `.svelte` source code into a JavaScript module that exports a component <div class="ts-block"> ```dts function compile( source: string, options: CompileOptions ): CompileResult; ``` </div> ## compileModule `compileModule` takes your JavaScript source code containing runes, and turns it into a JavaScript module. <div class="ts-block"> ```dts function compileModule( source: string, options: ModuleCompileOptions ): CompileResult; ``` </div> ## migrate Does a best-effort migration of Svelte code towards using runes, event attributes and render tags. May throw an error if the code is too complex to migrate automatically. <div class="ts-block"> ```dts function migrate( source: string, { filename, use_ts }?: | { filename?: string; use_ts?: boolean; } | undefined ): { code: string; }; ``` </div> ## parse The parse function parses a component, returning only its abstract syntax tree. The `modern` option (`false` by default in Svelte 5) makes the parser return a modern AST instead of the legacy AST. `modern` will become `true` by default in Svelte 6, and the option will be removed in Svelte 7. <div class="ts-block"> ```dts function parse( source: string, options: { filename?: string; modern: true; loose?: boolean; } ): AST.Root; ``` </div> <div class="ts-block"> ```dts function parse( source: string, options?: | { filename?: string; modern?: false; loose?: boolean; } | undefined ): Record<string, any>; ``` </div> ## preprocess The preprocess function provides convenient hooks for arbitrarily transforming component source code. For example, it can be used to convert a `<style lang="sass">` block into vanilla CSS. <div class="ts-block"> ```dts function preprocess( source: string, preprocessor: PreprocessorGroup | PreprocessorGroup[], options?: | { filename?: string; } | undefined ): Promise<Processed>; ``` </div> ## walk <blockquote class="tag deprecated note"> Replace this with `import { walk } from 'estree-walker'` </blockquote> <div class="ts-block"> ```dts function walk(): never; ``` </div> ## AST <div class="ts-block"> ```dts namespace AST { export interface BaseNode { type: string; start: number; end: number; } export interface Fragment { type: 'Fragment'; nodes: Array< Text | Tag | ElementLike | Block | Comment >; } export interface Root extends BaseNode { type: 'Root'; /** * Inline options provided by `<svelte:options>` — these override options passed to `compile(...)` */ options: SvelteOptions | null; fragment: Fragment; /** The parsed `<style>` element, if exists */ css: AST.CSS.StyleSheet | null; /** The parsed `<script>` element, if exists */ instance: Script | null; /** The parsed `<script module>` element, if exists */ module: Script | null; } export interface SvelteOptions { // start/end info (needed for warnings and for our Prettier plugin) start: number; end: number; // options runes?: boolean; immutable?: boolean; accessors?: boolean; preserveWhitespace?: boolean; namespace?: Namespace; css?: 'injected'; customElement?: { tag?: string; shadow?: 'open' | 'none'; props?: Record< string, { attribute?: string; reflect?: boolean; type?: | 'Array' | 'Boolean' | 'Number' | 'Object' | 'String'; } >; /** * Is of type * ```ts * (ceClass: new () => HTMLElement) => new () => HTMLElement * ``` */ extend?: ArrowFunctionExpression | Identifier; }; attributes: Attribute[]; } /** Static text */ export interface Text extends BaseNode { type: 'Text'; /** Text with decoded HTML entities */ data: string; /** The original text, with undecoded HTML entities */ raw: string; } /** A (possibly reactive) template expression — `{...}` */ export interface ExpressionTag extends BaseNode { type: 'ExpressionTag'; expression: Expression; } /** A (possibly reactive) HTML template expression — `{@html ...}` */ export interface HtmlTag extends BaseNode { type: 'HtmlTag'; expression: Expression; } /** An HTML comment */ // TODO rename to disambiguate export interface Comment extends BaseNode { type: 'Comment'; /** the contents of the comment */ data: string; } /** A `{@const ...}` tag */ export interface ConstTag extends BaseNode { type: 'ConstTag'; declaration: VariableDeclaration & { declarations: [ VariableDeclarator & { id: Pattern; init: Expression; } ]; }; } /** A `{@debug ...}` tag */ export interface DebugTag extends BaseNode { type: 'DebugTag'; identifiers: Identifier[]; } /** A `{@render foo(...)} tag */ export interface RenderTag extends BaseNode { type: 'RenderTag'; expression: | SimpleCallExpression | (ChainExpression & { expression: SimpleCallExpression; }); } /** An `animate:` directive */ export interface AnimateDirective extends BaseNode { type: 'AnimateDirective'; /** The 'x' in `animate:x` */ name: string; /** The y in `animate:x={y}` */ expression: null | Expression; } /** A `bind:` directive */ export interface BindDirective extends BaseNode { type: 'BindDirective'; /** The 'x' in `bind:x` */ name: string; /** The y in `bind:x={y}` */ expression: | Identifier | MemberExpression | SequenceExpression; } /** A `class:` directive */ export interface ClassDirective extends BaseNode { type: 'ClassDirective'; /** The 'x' in `class:x` */ name: 'class'; /** The 'y' in `class:x={y}`, or the `x` in `class:x` */ expression: Expression; } /** A `let:` directive */ export interface LetDirective extends BaseNode { type: 'LetDirective'; /** The 'x' in `let:x` */ name: string; /** The 'y' in `let:x={y}` */ expression: | null | Identifier | ArrayExpression | ObjectExpression; } /** An `on:` directive */ export interface OnDirective extends BaseNode { type: 'OnDirective'; /** The 'x' in `on:x` */ name: string; /** The 'y' in `on:x={y}` */ expression: null | Expression; modifiers: string[]; } /** A `style:` directive */ export interface StyleDirective extends BaseNode { type: 'StyleDirective'; /** The 'x' in `style:x` */ name: string; /** The 'y' in `style:x={y}` */ value: | true | ExpressionTag | Array<ExpressionTag | Text>; modifiers: Array<'important'>; } // TODO have separate in/out/transition directives /** A `transition:`, `in:` or `out:` directive */ export interface TransitionDirective extends BaseNode { type: 'TransitionDirective'; /** The 'x' in `transition:x` */ name: string; /** The 'y' in `transition:x={y}` */ expression: null | Expression; modifiers: Array<'local' | 'global'>; /** True if this is a `transition:` or `in:` directive */ intro: boolean; /** True if this is a `transition:` or `out:` directive */ outro: boolean; } /** A `use:` directive */ export interface UseDirective extends BaseNode { type: 'UseDirective'; /** The 'x' in `use:x` */ name: string; /** The 'y' in `use:x={y}` */ expression: null | Expression; } interface BaseElement extends BaseNode { name: string; attributes: Array< Attribute | SpreadAttribute | Directive >; fragment: Fragment; } export interface Component extends BaseElement { type: 'Component'; } export interface TitleElement extends BaseElement { type: 'TitleElement'; name: 'title'; } export interface SlotElement extends BaseElement { type: 'SlotElement'; name: 'slot'; } export interface RegularElement extends BaseElement { type: 'RegularElement'; } export interface SvelteBody extends BaseElement { type: 'SvelteBody'; name: 'svelte:body'; } export interface SvelteComponent extends BaseElement { type: 'SvelteComponent'; name: 'svelte:component'; expression: Expression; } export interface SvelteDocument extends BaseElement { type: 'SvelteDocument'; name: 'svelte:document'; } export interface SvelteElement extends BaseElement { type: 'SvelteElement'; name: 'svelte:element'; tag: Expression; } export interface SvelteFragment extends BaseElement { type: 'SvelteFragment'; name: 'svelte:fragment'; } export interface SvelteBoundary extends BaseElement { type: 'SvelteBoundary'; name: 'svelte:boundary'; } export interface SvelteHead extends BaseElement { type: 'SvelteHead'; name: 'svelte:head'; } /** This is only an intermediate representation while parsing, it doesn't exist in the final AST */ export interface SvelteOptionsRaw extends BaseElement { type: 'SvelteOptions'; name: 'svelte:options'; } export interface SvelteSelf extends BaseElement { type: 'SvelteSelf'; name: 'svelte:self'; } export interface SvelteWindow extends BaseElement { type: 'SvelteWindow'; name: 'svelte:window'; } /** An `{#each ...}` block */ export interface EachBlock extends BaseNode { type: 'EachBlock'; expression: Expression; /** The `entry` in `{#each item as entry}`. `null` if `as` part is omitted */ context: Pattern | null; body: Fragment; fallback?: Fragment; index?: string; key?: Expression; } /** An `{#if ...}` block */ export interface IfBlock extends BaseNode { type: 'IfBlock'; elseif: boolean; test: Expression; consequent: Fragment; alternate: Fragment | null; } /** An `{#await ...}` block */ export interface AwaitBlock extends BaseNode { type: 'AwaitBlock'; expression: Expression; // TODO can/should we move these inside the ThenBlock and CatchBlock? /** The resolved value inside the `then` block */ value: Pattern | null; /** The rejection reason inside the `catch` block */ error: Pattern | null; pending: Fragment | null; then: Fragment | null; catch: Fragment | null; } export interface KeyBlock extends BaseNode { type: 'KeyBlock'; expression: Expression; fragment: Fragment; } export interface SnippetBlock extends BaseNode { type: 'SnippetBlock'; expression: Identifier; parameters: Pattern[]; body: Fragment; } export interface Attribute extends BaseNode { type: 'Attribute'; name: string; /** * Quoted/string values are represented by an array, even if they contain a single expression like `"{x}"` */ value: | true | ExpressionTag | Array<Text | ExpressionTag>; } export interface SpreadAttribute extends BaseNode { type: 'SpreadAttribute'; expression: Expression; } export interface Script extends BaseNode { type: 'Script'; context: 'default' | 'module'; content: Program; attributes: Attribute[]; } export type AttributeLike = | Attribute | SpreadAttribute | Directive; export type Directive = | AST.AnimateDirective | AST.BindDirective | AST.ClassDirective | AST.LetDirective | AST.OnDirective | AST.StyleDirective | AST.TransitionDirective | AST.UseDirective; export type Block = | AST.EachBlock | AST.IfBlock | AST.AwaitBlock | AST.KeyBlock | AST.SnippetBlock; export type ElementLike = | AST.Component | AST.TitleElement | AST.SlotElement | AST.RegularElement | AST.SvelteBody | AST.SvelteBoundary | AST.SvelteComponent | AST.SvelteDocument | AST.SvelteElement | AST.SvelteFragment | AST.SvelteHead | AST.SvelteOptionsRaw | AST.SvelteSelf | AST.SvelteWindow | AST.SvelteBoundary; export type Tag = | AST.ExpressionTag | AST.HtmlTag | AST.ConstTag | AST.DebugTag | AST.RenderTag; export type TemplateNode = | AST.Root | AST.Text | Tag | ElementLike | AST.Attribute | AST.SpreadAttribute | Directive | AST.Comment | Block; export type SvelteNode = | Node | TemplateNode | AST.Fragment | _CSS.Node; export type { _CSS as CSS }; } ``` </div> ## CompileError <div class="ts-block"> ```dts interface CompileError extends ICompileDiagnostic {} ``` </div> ## CompileOptions <div class="ts-block"> ```dts interface CompileOptions extends ModuleCompileOptions {/*…*/} ``` <div class="ts-block-property"> ```dts name?: string; ``` <div class="ts-block-property-details"> Sets the name of the resulting JavaScript class (though the compiler will rename it if it would otherwise conflict with other variables in scope). If unspecified, will be inferred from `filename` </div> </div> <div class="ts-block-property"> ```dts customElement?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `false` </div> If `true`, tells the compiler to generate a custom element constructor instead of a regular Svelte component. </div> </div> <div class="ts-block-property"> ```dts accessors?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `false` - <span class="tag deprecated">deprecated</span> This will have no effect in runes mode </div> If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`. </div> </div> <div class="ts-block-property"> ```dts namespace?: Namespace; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `'html'` </div> The namespace of the element; e.g., `"html"`, `"svg"`, `"mathml"`. </div> </div> <div class="ts-block-property"> ```dts immutable?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `false` - <span class="tag deprecated">deprecated</span> This will have no effect in runes mode </div> If `true`, tells the compiler that you promise not to mutate any objects. This allows it to be less conservative about checking whether values have changed. </div> </div> <div class="ts-block-property"> ```dts css?: 'injected' | 'external'; ``` <div class="ts-block-property-details"> - `'injected'`: styles will be included in the `head` when using `render(...)`, and injected into the document (if not already present) when the component mounts. For components compiled as custom elements, styles are injected to the shadow root. - `'external'`: the CSS will only be returned in the `css` field of the compilation result. Most Svelte bundler plugins will set this to `'external'` and use the CSS that is statically generated for better performance, as it will result in smaller JavaScript bundles and the output can be served as cacheable `.css` files. This is always `'injected'` when compiling with `customElement` mode. </div> </div> <div class="ts-block-property"> ```dts cssHash?: CssHashGetter; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `undefined` </div> A function that takes a `{ hash, css, name, filename }` argument and returns the string that is used as a classname for scoped CSS. It defaults to returning `svelte-${hash(css)}`. </div> </div> <div class="ts-block-property"> ```dts preserveComments?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `false` </div> If `true`, your HTML comments will be preserved in the output. By default, they are stripped out. </div> </div> <div class="ts-block-property"> ```dts preserveWhitespace?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `false` </div> If `true`, whitespace inside and between elements is kept as you typed it, rather than removed or collapsed to a single space where possible. </div> </div> <div class="ts-block-property"> ```dts runes?: boolean | undefined; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `undefined` </div> Set to `true` to force the compiler into runes mode, even if there are no indications of runes usage. Set to `false` to force the compiler into ignoring runes, even if there are indications of runes usage. Set to `undefined` (the default) to infer runes mode from the component code. Is always `true` for JS/TS modules compiled with Svelte. Will be `true` by default in Svelte 6. Note that setting this to `true` in your `svelte.config.js` will force runes mode for your entire project, including components in `node_modules`, which is likely not what you want. If you're using Vite, consider using [dynamicCompileOptions](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md#dynamiccompileoptions) instead. </div> </div> <div class="ts-block-property"> ```dts discloseVersion?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `true` </div> If `true`, exposes the Svelte major version in the browser by adding it to a `Set` stored in the global `window.__svelte.v`. </div> </div> <div class="ts-block-property"> ```dts compatibility?: {/*…*/} ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> Use these only as a temporary solution before migrating your code </div> <div class="ts-block-property-children"><div class="ts-block-property"> ```dts componentApi?: 4 | 5; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `5` </div> Applies a transformation so that the default export of Svelte files can still be instantiated the same way as in Svelte 4 — as a class when compiling for the browser (as though using `createClassComponent(MyComponent, {...})` from `svelte/legacy`) or as an object with a `.render(...)` method when compiling for the server </div> </div></div> </div> </div> <div class="ts-block-property"> ```dts sourcemap?: object | string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `null` </div> An initial sourcemap that will be merged into the final output sourcemap. This is usually the preprocessor sourcemap. </div> </div> <div class="ts-block-property"> ```dts outputFilename?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `null` </div> Used for your JavaScript sourcemap. </div> </div> <div class="ts-block-property"> ```dts cssOutputFilename?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `null` </div> Used for your CSS sourcemap. </div> </div> <div class="ts-block-property"> ```dts hmr?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `false` </div> If `true`, compiles components with hot reloading support. </div> </div> <div class="ts-block-property"> ```dts modernAst?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `false` </div> If `true`, returns the modern version of the AST. Will become `true` by default in Svelte 6, and the option will be removed in Svelte 7. </div> </div></div> ## CompileResult The return value of `compile` from `svelte/compiler` <div class="ts-block"> ```dts interface CompileResult {/*…*/} ``` <div class="ts-block-property"> ```dts js: {/*…*/} ``` <div class="ts-block-property-details"> The compiled JavaScript <div class="ts-block-property-children"><div class="ts-block-property"> ```dts code: string; ``` <div class="ts-block-property-details"> The generated code </div> </div> <div class="ts-block-property"> ```dts map: SourceMap; ``` <div class="ts-block-property-details"> A source map </div> </div></div> </div> </div> <div class="ts-block-property"> ```dts css: null | { /** The generated code */ code: string; /** A source map */ map: SourceMap; }; ``` <div class="ts-block-property-details"> The compiled CSS </div> </div> <div class="ts-block-property"> ```dts warnings: Warning[]; ``` <div class="ts-block-property-details"> An array of warning objects that were generated during compilation. Each warning has several properties: - `code` is a string identifying the category of warning - `message` describes the issue in human-readable terms - `start` and `end`, if the warning relates to a specific location, are objects with `line`, `column` and `character` properties </div> </div> <div class="ts-block-property"> ```dts metadata: {/*…*/} ``` <div class="ts-block-property-details"> Metadata about the compiled component <div class="ts-block-property-children"><div class="ts-block-property"> ```dts runes: boolean; ``` <div class="ts-block-property-details"> Whether the file was compiled in runes mode, either because of an explicit option or inferred from usage. For `compileModule`, this is always `true` </div> </div> <div class="ts-block-property"> ```dts hasUnscopedGlobalCss: boolean; ``` <div class="ts-block-property-details"> Whether the component contains a top level :global selector or not For `compileModule`, this is always `true` </div> </div></div> </div> </div> <div class="ts-block-property"> ```dts ast: any; ``` <div class="ts-block-property-details"> The AST </div> </div></div> ## MarkupPreprocessor A markup preprocessor that takes a string of code and returns a processed version. <div class="ts-block"> ```dts type MarkupPreprocessor = (options: { /** * The whole Svelte file content */ content: string; /** * The filename of the Svelte file */ filename?: string; }) => Processed | void | Promise<Processed | void>; ``` </div> ## ModuleCompileOptions <div class="ts-block"> ```dts interface ModuleCompileOptions {/*…*/} ``` <div class="ts-block-property"> ```dts dev?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `false` </div> If `true`, causes extra code to be added that will perform runtime checks and provide debugging information during development. </div> </div> <div class="ts-block-property"> ```dts generate?: 'client' | 'server' | false; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `'client'` </div> If `"client"`, Svelte emits code designed to run in the browser. If `"server"`, Svelte emits code suitable for server-side rendering. If `false`, nothing is generated. Useful for tooling that is only interested in warnings. </div> </div> <div class="ts-block-property"> ```dts filename?: string; ``` <div class="ts-block-property-details"> Used for debugging hints and sourcemaps. Your bundler plugin will set it automatically. </div> </div> <div class="ts-block-property"> ```dts rootDir?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `process.cwd() on node-like environments, undefined elsewhere` </div> Used for ensuring filenames don't leak filesystem information. Your bundler plugin will set it automatically. </div> </div> <div class="ts-block-property"> ```dts warningFilter?: (warning: Warning) => boolean; ``` <div class="ts-block-property-details"> A function that gets a `Warning` as an argument and returns a boolean. Use this to filter out warnings. Return `true` to keep the warning, `false` to discard it. </div> </div></div> ## Preprocessor A script/style preprocessor that takes a string of code and returns a processed version. <div class="ts-block"> ```dts type Preprocessor = (options: { /** * The script/style tag content */ content: string; /** * The attributes on the script/style tag */ attributes: Record<string, string | boolean>; /** * The whole Svelte file content */ markup: string; /** * The filename of the Svelte file */ filename?: string; }) => Processed | void | Promise<Processed | void>; ``` </div> ## PreprocessorGroup A preprocessor group is a set of preprocessors that are applied to a Svelte file. <div class="ts-block"> ```dts interface PreprocessorGroup {/*…*/} ``` <div class="ts-block-property"> ```dts name?: string; ``` <div class="ts-block-property-details"> Name of the preprocessor. Will be a required option in the next major version </div> </div> <div class="ts-block-property"> ```dts markup?: MarkupPreprocessor; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts style?: Preprocessor; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts script?: Preprocessor; ``` <div class="ts-block-property-details"></div> </div></div> ## Processed The result of a preprocessor run. If the preprocessor does not return a result, it is assumed that the code is unchanged. <div class="ts-block"> ```dts interface Processed {/*…*/} ``` <div class="ts-block-property"> ```dts code: string; ``` <div class="ts-block-property-details"> The new code </div> </div> <div class="ts-block-property"> ```dts map?: string | object; ``` <div class="ts-block-property-details"> A source map mapping back to the original code </div> </div> <div class="ts-block-property"> ```dts dependencies?: string[]; ``` <div class="ts-block-property-details"> A list of additional files to watch for changes </div> </div> <div class="ts-block-property"> ```dts attributes?: Record<string, string | boolean>; ``` <div class="ts-block-property-details"> Only for script/style preprocessors: The updated attributes to set on the tag. If undefined, attributes stay unchanged. </div> </div> <div class="ts-block-property"> ```dts toString?: () => string; ``` <div class="ts-block-property-details"></div> </div></div> ## Warning <div class="ts-block"> ```dts interface Warning extends ICompileDiagnostic {} ``` </div>

# svelte/easing

```js // @noErrors import { backIn, backInOut, backOut, bounceIn, bounceInOut, bounceOut, circIn, circInOut, circOut, cubicIn, cubicInOut, cubicOut, elasticIn, elasticInOut, elasticOut, expoIn, expoInOut, expoOut, linear, quadIn, quadInOut, quadOut, quartIn, quartInOut, quartOut, quintIn, quintInOut, quintOut, sineIn, sineInOut, sineOut } from 'svelte/easing'; ``` ## backIn <div class="ts-block"> ```dts function backIn(t: number): number; ``` </div> ## backInOut <div class="ts-block"> ```dts function backInOut(t: number): number; ``` </div> ## backOut <div class="ts-block"> ```dts function backOut(t: number): number; ``` </div> ## bounceIn <div class="ts-block"> ```dts function bounceIn(t: number): number; ``` </div> ## bounceInOut <div class="ts-block"> ```dts function bounceInOut(t: number): number; ``` </div> ## bounceOut <div class="ts-block"> ```dts function bounceOut(t: number): number; ``` </div> ## circIn <div class="ts-block"> ```dts function circIn(t: number): number; ``` </div> ## circInOut <div class="ts-block"> ```dts function circInOut(t: number): number; ``` </div> ## circOut <div class="ts-block"> ```dts function circOut(t: number): number; ``` </div> ## cubicIn <div class="ts-block"> ```dts function cubicIn(t: number): number; ``` </div> ## cubicInOut <div class="ts-block"> ```dts function cubicInOut(t: number): number; ``` </div> ## cubicOut <div class="ts-block"> ```dts function cubicOut(t: number): number; ``` </div> ## elasticIn <div class="ts-block"> ```dts function elasticIn(t: number): number; ``` </div> ## elasticInOut <div class="ts-block"> ```dts function elasticInOut(t: number): number; ``` </div> ## elasticOut <div class="ts-block"> ```dts function elasticOut(t: number): number; ``` </div> ## expoIn <div class="ts-block"> ```dts function expoIn(t: number): number; ``` </div> ## expoInOut <div class="ts-block"> ```dts function expoInOut(t: number): number; ``` </div> ## expoOut <div class="ts-block"> ```dts function expoOut(t: number): number; ``` </div> ## linear <div class="ts-block"> ```dts function linear(t: number): number; ``` </div> ## quadIn <div class="ts-block"> ```dts function quadIn(t: number): number; ``` </div> ## quadInOut <div class="ts-block"> ```dts function quadInOut(t: number): number; ``` </div> ## quadOut <div class="ts-block"> ```dts function quadOut(t: number): number; ``` </div> ## quartIn <div class="ts-block"> ```dts function quartIn(t: number): number; ``` </div> ## quartInOut <div class="ts-block"> ```dts function quartInOut(t: number): number; ``` </div> ## quartOut <div class="ts-block"> ```dts function quartOut(t: number): number; ``` </div> ## quintIn <div class="ts-block"> ```dts function quintIn(t: number): number; ``` </div> ## quintInOut <div class="ts-block"> ```dts function quintInOut(t: number): number; ``` </div> ## quintOut <div class="ts-block"> ```dts function quintOut(t: number): number; ``` </div> ## sineIn <div class="ts-block"> ```dts function sineIn(t: number): number; ``` </div> ## sineInOut <div class="ts-block"> ```dts function sineInOut(t: number): number; ``` </div> ## sineOut <div class="ts-block"> ```dts function sineOut(t: number): number; ``` </div>

# svelte/events

```js // @noErrors import { on } from 'svelte/events'; ``` ## on Attaches an event handler to the window and returns a function that removes the handler. Using this rather than `addEventListener` will preserve the correct order relative to handlers added declaratively (with attributes like `onclick`), which use event delegation for performance reasons <div class="ts-block"> ```dts function on<Type extends keyof WindowEventMap>( window: Window, type: Type, handler: ( this: Window, event: WindowEventMap[Type] ) => any, options?: AddEventListenerOptions | undefined ): () => void; ``` </div> <div class="ts-block"> ```dts function on<Type extends keyof DocumentEventMap>( document: Document, type: Type, handler: ( this: Document, event: DocumentEventMap[Type] ) => any, options?: AddEventListenerOptions | undefined ): () => void; ``` </div> <div class="ts-block"> ```dts function on< Element extends HTMLElement, Type extends keyof HTMLElementEventMap >( element: Element, type: Type, handler: ( this: Element, event: HTMLElementEventMap[Type] ) => any, options?: AddEventListenerOptions | undefined ): () => void; ``` </div> <div class="ts-block"> ```dts function on< Element extends MediaQueryList, Type extends keyof MediaQueryListEventMap >( element: Element, type: Type, handler: ( this: Element, event: MediaQueryListEventMap[Type] ) => any, options?: AddEventListenerOptions | undefined ): () => void; ``` </div> <div class="ts-block"> ```dts function on( element: EventTarget, type: string, handler: EventListener, options?: AddEventListenerOptions | undefined ): () => void; ``` </div>

# svelte/motion

```js // @noErrors import { Spring, Tween, prefersReducedMotion, spring, tweened } from 'svelte/motion'; ``` ## Spring <blockquote class="since note"> Available since 5.8.0 </blockquote> A wrapper for a value that behaves in a spring-like fashion. Changes to `spring.target` will cause `spring.current` to move towards it over time, taking account of the `spring.stiffness` and `spring.damping` parameters. ```svelte <script> import { Spring } from 'svelte/motion'; const spring = new Spring(0); </script> <input type="range" bind:value={spring.target} /> <input type="range" bind:value={spring.current} disabled /> ``` <div class="ts-block"> ```dts class Spring<T> {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(value: T, options?: SpringOpts); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts static of<U>(fn: () => U, options?: SpringOpts): Spring<U>; ``` <div class="ts-block-property-details"> Create a spring whose value is bound to the return value of `fn`. This must be called inside an effect root (for example, during component initialisation). ```svelte <script> import { Spring } from 'svelte/motion'; let { number } = $props(); const spring = Spring.of(() => number); </script> ``` </div> </div> <div class="ts-block-property"> ```dts set(value: T, options?: SpringUpdateOpts): Promise<void>; ``` <div class="ts-block-property-details"> Sets `spring.target` to `value` and returns a `Promise` that resolves if and when `spring.current` catches up to it. If `options.instant` is `true`, `spring.current` immediately matches `spring.target`. If `options.preserveMomentum` is provided, the spring will continue on its current trajectory for the specified number of milliseconds. This is useful for things like 'fling' gestures. </div> </div> <div class="ts-block-property"> ```dts damping: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts precision: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts stiffness: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts target: T; ``` <div class="ts-block-property-details"> The end value of the spring. This property only exists on the `Spring` class, not the legacy `spring` store. </div> </div> <div class="ts-block-property"> ```dts get current(): T; ``` <div class="ts-block-property-details"> The current value of the spring. This property only exists on the `Spring` class, not the legacy `spring` store. </div> </div></div> ## Tween <blockquote class="since note"> Available since 5.8.0 </blockquote> A wrapper for a value that tweens smoothly to its target value. Changes to `tween.target` will cause `tween.current` to move towards it over time, taking account of the `delay`, `duration` and `easing` options. ```svelte <script> import { Tween } from 'svelte/motion'; const tween = new Tween(0); </script> <input type="range" bind:value={tween.target} /> <input type="range" bind:value={tween.current} disabled /> ``` <div class="ts-block"> ```dts class Tween<T> {/*…*/} ``` <div class="ts-block-property"> ```dts static of<U>(fn: () => U, options?: TweenedOptions<U> | undefined): Tween<U>; ``` <div class="ts-block-property-details"> Create a tween whose value is bound to the return value of `fn`. This must be called inside an effect root (for example, during component initialisation). ```svelte <script> import { Tween } from 'svelte/motion'; let { number } = $props(); const tween = Tween.of(() => number); </script> ``` </div> </div> <div class="ts-block-property"> ```dts constructor(value: T, options?: TweenedOptions<T>); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts set(value: T, options?: TweenedOptions<T> | undefined): Promise<void>; ``` <div class="ts-block-property-details"> Sets `tween.target` to `value` and returns a `Promise` that resolves if and when `tween.current` catches up to it. If `options` are provided, they will override the tween's defaults. </div> </div> <div class="ts-block-property"> ```dts get current(): T; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts set target(v: T); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts get target(): T; ``` <div class="ts-block-property-details"></div> </div></div> ## prefersReducedMotion <blockquote class="since note"> Available since 5.7.0 </blockquote> A [media query](/docs/svelte/svelte-reactivity#MediaQuery) that matches if the user [prefers reduced motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion). ```svelte <script> import { prefersReducedMotion } from 'svelte/motion'; import { fly } from 'svelte/transition'; let visible = $state(false); </script> <button onclick={() => visible = !visible}> toggle </button> {#if visible} <p transition:fly={{ y: prefersReducedMotion.current ? 0 : 200 }}> flies in, unless the user prefers reduced motion </p> {/if} ``` <div class="ts-block"> ```dts const prefersReducedMotion: MediaQuery; ``` </div> ## spring <blockquote class="tag deprecated note"> Use [`Spring`](/docs/svelte/svelte-motion#Spring) instead </blockquote> The spring function in Svelte creates a store whose value is animated, with a motion that simulates the behavior of a spring. This means when the value changes, instead of transitioning at a steady rate, it "bounces" like a spring would, depending on the physics parameters provided. This adds a level of realism to the transitions and can enhance the user experience. <div class="ts-block"> ```dts function spring<T = any>( value?: T | undefined, opts?: SpringOpts | undefined ): Spring<T>; ``` </div> ## tweened <blockquote class="tag deprecated note"> Use [`Tween`](/docs/svelte/svelte-motion#Tween) instead </blockquote> A tweened store in Svelte is a special type of store that provides smooth transitions between state values over time. <div class="ts-block"> ```dts function tweened<T>( value?: T | undefined, defaults?: TweenedOptions<T> | undefined ): Tweened<T>; ``` </div> ## Spring <div class="ts-block"> ```dts interface Spring<T> extends Readable<T> {/*…*/} ``` <div class="ts-block-property"> ```dts set(new_value: T, opts?: SpringUpdateOpts): Promise<void>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts update: (fn: Updater<T>, opts?: SpringUpdateOpts) => Promise<void>; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> Only exists on the legacy `spring` store, not the `Spring` class </div> </div> </div> <div class="ts-block-property"> ```dts subscribe(fn: (value: T) => void): Unsubscriber; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> Only exists on the legacy `spring` store, not the `Spring` class </div> </div> </div> <div class="ts-block-property"> ```dts precision: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts damping: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts stiffness: number; ``` <div class="ts-block-property-details"></div> </div></div> ## Tweened <div class="ts-block"> ```dts interface Tweened<T> extends Readable<T> {/*…*/} ``` <div class="ts-block-property"> ```dts set(value: T, opts?: TweenedOptions<T>): Promise<void>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts update(updater: Updater<T>, opts?: TweenedOptions<T>): Promise<void>; ``` <div class="ts-block-property-details"></div> </div></div>

# svelte/reactivity/window

This module exports reactive versions of various `window` values, each of which has a reactive `current` property that you can reference in reactive contexts (templates, [deriveds]($derived) and [effects]($effect)) without using [`<svelte:window>`](svelte-window) bindings or manually creating your own event listeners. ```svelte <script> import { innerWidth, innerHeight } from 'svelte/reactivity/window'; </script> <p>{innerWidth.current}x{innerHeight.current}</p> ``` ```js // @noErrors import { devicePixelRatio, innerHeight, innerWidth, online, outerHeight, outerWidth, screenLeft, screenTop, scrollX, scrollY } from 'svelte/reactivity/window'; ``` ## devicePixelRatio <blockquote class="since note"> Available since 5.11.0 </blockquote> `devicePixelRatio.current` is a reactive view of `window.devicePixelRatio`. On the server it is `undefined`. Note that behaviour differs between browsers — on Chrome it will respond to the current zoom level, on Firefox and Safari it won't. <div class="ts-block"> ```dts const devicePixelRatio: { get current(): number | undefined; }; ``` </div> ## innerHeight <blockquote class="since note"> Available since 5.11.0 </blockquote> `innerHeight.current` is a reactive view of `window.innerHeight`. On the server it is `undefined`. <div class="ts-block"> ```dts const innerHeight: ReactiveValue<number | undefined>; ``` </div> ## innerWidth <blockquote class="since note"> Available since 5.11.0 </blockquote> `innerWidth.current` is a reactive view of `window.innerWidth`. On the server it is `undefined`. <div class="ts-block"> ```dts const innerWidth: ReactiveValue<number | undefined>; ``` </div> ## online <blockquote class="since note"> Available since 5.11.0 </blockquote> `online.current` is a reactive view of `navigator.onLine`. On the server it is `undefined`. <div class="ts-block"> ```dts const online: ReactiveValue<boolean | undefined>; ``` </div> ## outerHeight <blockquote class="since note"> Available since 5.11.0 </blockquote> `outerHeight.current` is a reactive view of `window.outerHeight`. On the server it is `undefined`. <div class="ts-block"> ```dts const outerHeight: ReactiveValue<number | undefined>; ``` </div> ## outerWidth <blockquote class="since note"> Available since 5.11.0 </blockquote> `outerWidth.current` is a reactive view of `window.outerWidth`. On the server it is `undefined`. <div class="ts-block"> ```dts const outerWidth: ReactiveValue<number | undefined>; ``` </div> ## screenLeft <blockquote class="since note"> Available since 5.11.0 </blockquote> `screenLeft.current` is a reactive view of `window.screenLeft`. It is updated inside a `requestAnimationFrame` callback. On the server it is `undefined`. <div class="ts-block"> ```dts const screenLeft: ReactiveValue<number | undefined>; ``` </div> ## screenTop <blockquote class="since note"> Available since 5.11.0 </blockquote> `screenTop.current` is a reactive view of `window.screenTop`. It is updated inside a `requestAnimationFrame` callback. On the server it is `undefined`. <div class="ts-block"> ```dts const screenTop: ReactiveValue<number | undefined>; ``` </div> ## scrollX <blockquote class="since note"> Available since 5.11.0 </blockquote> `scrollX.current` is a reactive view of `window.scrollX`. On the server it is `undefined`. <div class="ts-block"> ```dts const scrollX: ReactiveValue<number | undefined>; ``` </div> ## scrollY <blockquote class="since note"> Available since 5.11.0 </blockquote> `scrollY.current` is a reactive view of `window.scrollY`. On the server it is `undefined`. <div class="ts-block"> ```dts const scrollY: ReactiveValue<number | undefined>; ``` </div>

# svelte/reactivity

Svelte provides reactive versions of various built-ins like `SvelteMap`, `SvelteSet` and `SvelteURL`. These can be imported from `svelte/reactivity` and used just like their native counterparts. ```svelte <script> import { SvelteURL } from 'svelte/reactivity'; const url = new SvelteURL('https://example.com/path'); </script> <!-- changes to these... --> <input bind:value={url.protocol} /> <input bind:value={url.hostname} /> <input bind:value={url.pathname} /> <hr /> <!-- will update `href` and vice versa --> <input bind:value={url.href} /> ``` ```js // @noErrors import { MediaQuery, SvelteDate, SvelteMap, SvelteSet, SvelteURL, SvelteURLSearchParams, createSubscriber } from 'svelte/reactivity'; ``` ## MediaQuery <blockquote class="since note"> Available since 5.7.0 </blockquote> Creates a media query and provides a `current` property that reflects whether or not it matches. Use it carefully — during server-side rendering, there is no way to know what the correct value should be, potentially causing content to change upon hydration. If you can use the media query in CSS to achieve the same effect, do that. ```svelte <script> import { MediaQuery } from 'svelte/reactivity'; const large = new MediaQuery('min-width: 800px'); </script> <h1>{large.current ? 'large screen' : 'small screen'}</h1> ``` <div class="ts-block"> ```dts class MediaQuery extends ReactiveValue<boolean> {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(query: string, fallback?: boolean | undefined); ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `query` A media query string - `fallback` Fallback value for the server </div> </div> </div></div> ## SvelteDate <div class="ts-block"> ```dts class SvelteDate extends Date {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(...params: any[]); ``` <div class="ts-block-property-details"></div> </div></div> ## SvelteMap <div class="ts-block"> ```dts class SvelteMap<K, V> extends Map<K, V> {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(value?: Iterable<readonly [K, V]> | null | undefined); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts set(key: K, value: V): this; ``` <div class="ts-block-property-details"></div> </div></div> ## SvelteSet <div class="ts-block"> ```dts class SvelteSet<T> extends Set<T> {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(value?: Iterable<T> | null | undefined); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts add(value: T): this; ``` <div class="ts-block-property-details"></div> </div></div> ## SvelteURL <div class="ts-block"> ```dts class SvelteURL extends URL {/*…*/} ``` <div class="ts-block-property"> ```dts get searchParams(): SvelteURLSearchParams; ``` <div class="ts-block-property-details"></div> </div></div> ## SvelteURLSearchParams <div class="ts-block"> ```dts class SvelteURLSearchParams extends URLSearchParams {/*…*/} ``` <div class="ts-block-property"> ```dts [REPLACE](params: URLSearchParams): void; ``` <div class="ts-block-property-details"></div> </div></div> ## createSubscriber <blockquote class="since note"> Available since 5.7.0 </blockquote> Returns a `subscribe` function that, if called in an effect (including expressions in the template), calls its `start` callback with an `update` function. Whenever `update` is called, the effect re-runs. If `start` returns a function, it will be called when the effect is destroyed. If `subscribe` is called in multiple effects, `start` will only be called once as long as the effects are active, and the returned teardown function will only be called when all effects are destroyed. It's best understood with an example. Here's an implementation of [`MediaQuery`](/docs/svelte/svelte-reactivity#MediaQuery): ```js // @errors: 7031 import { createSubscriber } from 'svelte/reactivity'; import { on } from 'svelte/events'; export class MediaQuery { #query; #subscribe; constructor(query) { this.#query = window.matchMedia(`(${query})`); this.#subscribe = createSubscriber((update) => { // when the `change` event occurs, re-run any effects that read `this.current` const off = on(this.#query, 'change', update); // stop listening when all the effects are destroyed return () => off(); }); } get current() { this.#subscribe(); // Return the current state of the query, whether or not we're in an effect return this.#query.matches; } } ``` <div class="ts-block"> ```dts function createSubscriber( start: (update: () => void) => (() => void) | void ): () => void; ``` </div>

# svelte/server

```js // @noErrors import { render } from 'svelte/server'; ``` ## render Only available on the server and when compiling with the `server` option. Takes a component and returns an object with `body` and `head` properties on it, which you can use to populate the HTML when server-rendering your app. <div class="ts-block"> ```dts function render< Comp extends SvelteComponent<any> | Component<any>, Props extends ComponentProps<Comp> = ComponentProps<Comp> >( ...args: {} extends Props ? [ component: Comp extends SvelteComponent<any> ? ComponentType<Comp> : Comp, options?: { props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string; } ] : [ component: Comp extends SvelteComponent<any> ? ComponentType<Comp> : Comp, options: { props: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string; } ] ): RenderOutput; ``` </div>

# svelte/store

```js // @noErrors import { derived, fromStore, get, readable, readonly, toStore, writable } from 'svelte/store'; ``` ## derived Derived value store by synchronizing one or more readable stores and applying an aggregation function over its input values. <div class="ts-block"> ```dts function derived<S extends Stores, T>( stores: S, fn: ( values: StoresValues<S>, set: (value: T) => void, update: (fn: Updater<T>) => void ) => Unsubscriber | void, initial_value?: T | undefined ): Readable<T>; ``` </div> <div class="ts-block"> ```dts function derived<S extends Stores, T>( stores: S, fn: (values: StoresValues<S>) => T, initial_value?: T | undefined ): Readable<T>; ``` </div> ## fromStore <div class="ts-block"> ```dts function fromStore<V>(store: Writable<V>): { current: V; }; ``` </div> <div class="ts-block"> ```dts function fromStore<V>(store: Readable<V>): { readonly current: V; }; ``` </div> ## get Get the current value from a store by subscribing and immediately unsubscribing. <div class="ts-block"> ```dts function get<T>(store: Readable<T>): T; ``` </div> ## readable Creates a `Readable` store that allows reading by subscription. <div class="ts-block"> ```dts function readable<T>( value?: T | undefined, start?: StartStopNotifier<T> | undefined ): Readable<T>; ``` </div> ## readonly Takes a store and returns a new one derived from the old one that is readable. <div class="ts-block"> ```dts function readonly<T>(store: Readable<T>): Readable<T>; ``` </div> ## toStore <div class="ts-block"> ```dts function toStore<V>( get: () => V, set: (v: V) => void ): Writable<V>; ``` </div> <div class="ts-block"> ```dts function toStore<V>(get: () => V): Readable<V>; ``` </div> ## writable Create a `Writable` store that allows both updating and reading by subscription. <div class="ts-block"> ```dts function writable<T>( value?: T | undefined, start?: StartStopNotifier<T> | undefined ): Writable<T>; ``` </div> ## Readable Readable interface for subscribing. <div class="ts-block"> ```dts interface Readable<T> {/*…*/} ``` <div class="ts-block-property"> ```dts subscribe(this: void, run: Subscriber<T>, invalidate?: () => void): Unsubscriber; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `run` subscription callback - `invalidate` cleanup callback </div> Subscribe on value changes. </div> </div></div> ## StartStopNotifier Start and stop notification callbacks. This function is called when the first subscriber subscribes. <div class="ts-block"> ```dts type StartStopNotifier<T> = ( set: (value: T) => void, update: (fn: Updater<T>) => void ) => void | (() => void); ``` </div> ## Subscriber Callback to inform of a value updates. <div class="ts-block"> ```dts type Subscriber<T> = (value: T) => void; ``` </div> ## Unsubscriber Unsubscribes from value updates. <div class="ts-block"> ```dts type Unsubscriber = () => void; ``` </div> ## Updater Callback to update a value. <div class="ts-block"> ```dts type Updater<T> = (value: T) => T; ``` </div> ## Writable Writable interface for both updating and subscribing. <div class="ts-block"> ```dts interface Writable<T> extends Readable<T> {/*…*/} ``` <div class="ts-block-property"> ```dts set(this: void, value: T): void; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `value` to set </div> Set value and inform subscribers. </div> </div> <div class="ts-block-property"> ```dts update(this: void, updater: Updater<T>): void; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `updater` callback </div> Update value using callback and inform subscribers. </div> </div></div>

# svelte/transition

```js // @noErrors import { blur, crossfade, draw, fade, fly, scale, slide } from 'svelte/transition'; ``` ## blur Animates a `blur` filter alongside an element's opacity. <div class="ts-block"> ```dts function blur( node: Element, { delay, duration, easing, amount, opacity }?: BlurParams | undefined ): TransitionConfig; ``` </div> ## crossfade The `crossfade` function creates a pair of [transitions](/docs/svelte/transition) called `send` and `receive`. When an element is 'sent', it looks for a corresponding element being 'received', and generates a transition that transforms the element to its counterpart's position and fades it out. When an element is 'received', the reverse happens. If there is no counterpart, the `fallback` transition is used. <div class="ts-block"> ```dts function crossfade({ fallback, ...defaults }: CrossfadeParams & { fallback?: ( node: Element, params: CrossfadeParams, intro: boolean ) => TransitionConfig; }): [ ( node: any, params: CrossfadeParams & { key: any; } ) => () => TransitionConfig, ( node: any, params: CrossfadeParams & { key: any; } ) => () => TransitionConfig ]; ``` </div> ## draw Animates the stroke of an SVG element, like a snake in a tube. `in` transitions begin with the path invisible and draw the path to the screen over time. `out` transitions start in a visible state and gradually erase the path. `draw` only works with elements that have a `getTotalLength` method, like `<path>` and `<polyline>`. <div class="ts-block"> ```dts function draw( node: SVGElement & { getTotalLength(): number; }, { delay, speed, duration, easing }?: DrawParams | undefined ): TransitionConfig; ``` </div> ## fade Animates the opacity of an element from 0 to the current opacity for `in` transitions and from the current opacity to 0 for `out` transitions. <div class="ts-block"> ```dts function fade( node: Element, { delay, duration, easing }?: FadeParams | undefined ): TransitionConfig; ``` </div> ## fly Animates the x and y positions and the opacity of an element. `in` transitions animate from the provided values, passed as parameters to the element's default values. `out` transitions animate from the element's default values to the provided values. <div class="ts-block"> ```dts function fly( node: Element, { delay, duration, easing, x, y, opacity }?: FlyParams | undefined ): TransitionConfig; ``` </div> ## scale Animates the opacity and scale of an element. `in` transitions animate from the provided values, passed as parameters, to an element's current (default) values. `out` transitions animate from an element's default values to the provided values. <div class="ts-block"> ```dts function scale( node: Element, { delay, duration, easing, start, opacity }?: ScaleParams | undefined ): TransitionConfig; ``` </div> ## slide Slides an element in and out. <div class="ts-block"> ```dts function slide( node: Element, { delay, duration, easing, axis }?: SlideParams | undefined ): TransitionConfig; ``` </div> ## BlurParams <div class="ts-block"> ```dts interface BlurParams {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: EasingFunction; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts amount?: number | string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts opacity?: number; ``` <div class="ts-block-property-details"></div> </div></div> ## CrossfadeParams <div class="ts-block"> ```dts interface CrossfadeParams {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number | ((len: number) => number); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: EasingFunction; ``` <div class="ts-block-property-details"></div> </div></div> ## DrawParams <div class="ts-block"> ```dts interface DrawParams {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts speed?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number | ((len: number) => number); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: EasingFunction; ``` <div class="ts-block-property-details"></div> </div></div> ## EasingFunction <div class="ts-block"> ```dts type EasingFunction = (t: number) => number; ``` </div> ## FadeParams <div class="ts-block"> ```dts interface FadeParams {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: EasingFunction; ``` <div class="ts-block-property-details"></div> </div></div> ## FlyParams <div class="ts-block"> ```dts interface FlyParams {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: EasingFunction; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts x?: number | string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts y?: number | string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts opacity?: number; ``` <div class="ts-block-property-details"></div> </div></div> ## ScaleParams <div class="ts-block"> ```dts interface ScaleParams {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: EasingFunction; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts start?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts opacity?: number; ``` <div class="ts-block-property-details"></div> </div></div> ## SlideParams <div class="ts-block"> ```dts interface SlideParams {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: EasingFunction; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts axis?: 'x' | 'y'; ``` <div class="ts-block-property-details"></div> </div></div> ## TransitionConfig <div class="ts-block"> ```dts interface TransitionConfig {/*…*/} ``` <div class="ts-block-property"> ```dts delay?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts duration?: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts easing?: EasingFunction; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts css?: (t: number, u: number) => string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts tick?: (t: number, u: number) => void; ``` <div class="ts-block-property-details"></div> </div></div>
# Start of SvelteKit documentation


# Introduction

## Before we begin > > If you get stuck, reach out for help in the [Discord chatroom](/chat). ## What is SvelteKit? SvelteKit is a framework for rapidly developing robust, performant web applications using [Svelte](../svelte). If you're coming from React, SvelteKit is similar to Next. If you're coming from Vue, SvelteKit is similar to Nuxt. To learn more about the kinds of applications you can build with SvelteKit, see the [FAQ](faq#What-can-I-make-with-SvelteKit). ## What is Svelte? In short, Svelte is a way of writing user interface components — like a navigation bar, comment section, or contact form — that users see and interact with in their browsers. The Svelte compiler converts your components to JavaScript that can be run to render the HTML for the page and to CSS that styles the page. You don't need to know Svelte to understand the rest of this guide, but it will help. If you'd like to learn more, check out [the Svelte tutorial](/tutorial). ## SvelteKit vs Svelte Svelte renders UI components. You can compose these components and render an entire page with just Svelte, but you need more than just Svelte to write an entire app. SvelteKit helps you build web apps while following modern best practices and providing solutions to common development challenges. It offers everything from basic functionalities — like a [router](glossary#Routing) that updates your UI when a link is clicked — to more advanced capabilities. Its extensive list of features includes [build optimizations](https://vitejs.dev/guide/features.html#build-optimizations) to load only the minimal required code; [offline support](service-workers); [preloading](link-options#data-sveltekit-preload-data) pages before user navigation; [configurable rendering](page-options) to handle different parts of your app on the server via [SSR](glossary#SSR), in the browser through [client-side rendering](glossary#CSR), or at build-time with [prerendering](glossary#Prerendering); [image optimization](images); and much more. Building an app with all the modern best practices is fiendishly complicated, but SvelteKit does all the boring stuff for you so that you can get on with the creative part. It reflects changes to your code in the browser instantly to provide a lightning-fast and feature-rich development experience by leveraging [Vite](https://vitejs.dev/) with a [Svelte plugin](https://github.com/sveltejs/vite-plugin-svelte) to do [Hot Module Replacement (HMR)](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md#hot).

# Creating a project

The easiest way to start building a SvelteKit app is to run `npx sv create`: ```bash npx sv create my-app cd my-app npm install npm run dev ``` The first command will scaffold a new project in the `my-app` directory asking you if you'd like to set up some basic tooling such as TypeScript. See [integrations](./integrations) for pointers on setting up additional tooling. The subsequent commands will then install its dependencies and start a server on [localhost:5173](http://localhost:5173). There are two basic concepts: - Each page of your app is a [Svelte](../svelte) component - You create pages by adding files to the `src/routes` directory of your project. These will be server-rendered so that a user's first visit to your app is as fast as possible, then a client-side app takes over Try editing the files to get a feel for how everything works. ## Editor setup We recommend using [Visual Studio Code (aka VS Code)](https://code.visualstudio.com/download) with [the Svelte extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), but [support also exists for numerous other editors](https://sveltesociety.dev/resources#editor-support).

# Project structure

A typical SvelteKit project looks like this: ```bash my-project/ ├ src/ │ ├ lib/ │ │ ├ server/ │ │ │ └ [your server-only lib files] │ │ └ [your lib files] │ ├ params/ │ │ └ [your param matchers] │ ├ routes/ │ │ └ [your routes] │ ├ app.html │ ├ error.html │ ├ hooks.client.js │ ├ hooks.server.js │ └ service-worker.js ├ static/ │ └ [your static assets] ├ tests/ │ └ [your tests] ├ package.json ├ svelte.config.js ├ tsconfig.json └ vite.config.js ``` You'll also find common files like `.gitignore` and `.npmrc` (and `.prettierrc` and `eslint.config.js` and so on, if you chose those options when running `npx sv create`). ## Project files ### src The `src` directory contains the meat of your project. Everything except `src/routes` and `src/app.html` is optional. - `lib` contains your library code (utilities and components), which can be imported via the [`$lib`]($lib) alias, or packaged up for distribution using [`svelte-package`](packaging) - `server` contains your server-only library code. It can be imported by using the [`$lib/server`](server-only-modules) alias. SvelteKit will prevent you from importing these in client code. - `params` contains any [param matchers](advanced-routing#Matching) your app needs - `routes` contains the [routes](routing) of your application. You can also colocate other components that are only used within a single route here - `app.html` is your page template — an HTML document containing the following placeholders: - `%sveltekit.head%` — `<link>` and `<script>` elements needed by the app, plus any `<svelte:head>` content - `%sveltekit.body%` — the markup for a rendered page. This should live inside a `<div>` or other element, rather than directly inside `<body>`, to prevent bugs caused by browser extensions injecting elements that are then destroyed by the hydration process. SvelteKit will warn you in development if this is not the case - `%sveltekit.assets%` — either [`paths.assets`](configuration#paths), if specified, or a relative path to [`paths.base`](configuration#paths) - `%sveltekit.nonce%` — a [CSP](configuration#csp) nonce for manually included links and scripts, if used - `%sveltekit.env.[NAME]%` - this will be replaced at render time with the `[NAME]` environment variable, which must begin with the [`publicPrefix`](configuration#env) (usually `PUBLIC_`). It will fallback to `''` if not matched. - `error.html` is the page that is rendered when everything else fails. It can contain the following placeholders: - `%sveltekit.status%` — the HTTP status - `%sveltekit.error.message%` — the error message - `hooks.client.js` contains your client [hooks](hooks) - `hooks.server.js` contains your server [hooks](hooks) - `service-worker.js` contains your [service worker](service-workers) (Whether the project contains `.js` or `.ts` files depends on whether you opt to use TypeScript when you create your project. You can switch between JavaScript and TypeScript in the documentation using the toggle at the bottom of this page.) If you added [Vitest](https://vitest.dev) when you set up your project, your unit tests will live in the `src` directory with a `.test.js` extension. ### static Any static assets that should be served as-is, like `robots.txt` or `favicon.png`, go in here. ### tests If you added [Playwright](https://playwright.dev/) for browser testing when you set up your project, the tests will live in this directory. ### package.json Your `package.json` file must include `@sveltejs/kit`, `svelte` and `vite` as `devDependencies`. When you create a project with `npx sv create`, you'll also notice that `package.json` includes `"type": "module"`. This means that `.js` files are interpreted as native JavaScript modules with `import` and `export` keywords. Legacy CommonJS files need a `.cjs` file extension. ### svelte.config.js This file contains your Svelte and SvelteKit [configuration](configuration). ### tsconfig.json This file (or `jsconfig.json`, if you prefer type-checked `.js` files over `.ts` files) configures TypeScript, if you added typechecking during `npx sv create`. Since SvelteKit relies on certain configuration being set a specific way, it generates its own `.svelte-kit/tsconfig.json` file which your own config `extends`. ### vite.config.js A SvelteKit project is really just a [Vite](https://vitejs.dev) project that uses the [`@sveltejs/kit/vite`](@sveltejs-kit-vite) plugin, along with any other [Vite configuration](https://vitejs.dev/config/). ## Other files ### .svelte-kit As you develop and build your project, SvelteKit will generate files in a `.svelte-kit` directory (configurable as [`outDir`](configuration#outDir)). You can ignore its contents, and delete them at any time (they will be regenerated when you next `dev` or `build`).

# Web standards

Throughout this documentation, you'll see references to the standard [Web APIs](https://developer.mozilla.org/en-US/docs/Web/API) that SvelteKit builds on top of. Rather than reinventing the wheel, we _use the platform_, which means your existing web development skills are applicable to SvelteKit. Conversely, time spent learning SvelteKit will help you be a better web developer elsewhere. These APIs are available in all modern browsers and in many non-browser environments like Cloudflare Workers, Deno, and Vercel Functions. During development, and in [adapters](adapters) for Node-based environments (including AWS Lambda), they're made available via polyfills where necessary (for now, that is — Node is rapidly adding support for more web standards). In particular, you'll get comfortable with the following: ## Fetch APIs SvelteKit uses [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) for getting data from the network. It's available in [hooks](hooks) and [server routes](routing#server) as well as in the browser. Besides `fetch` itself, the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) includes the following interfaces: ### Request An instance of [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) is accessible in [hooks](hooks) and [server routes](routing#server) as `event.request`. It contains useful methods like `request.json()` and `request.formData()` for getting data that was posted to an endpoint. ### Response An instance of [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) is returned from `await fetch(...)` and handlers in `+server.js` files. Fundamentally, a SvelteKit app is a machine for turning a `Request` into a `Response`. ### Headers The [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) interface allows you to read incoming `request.headers` and set outgoing `response.headers`. For example, you can get the `request.headers` as shown below, and use the [`json` convenience function](@sveltejs-kit#json) to send modified `response.headers`: ```js // @errors: 2461 /// 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 When dealing with HTML native form submissions you'll be working with [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) objects. ```js // @errors: 2461 /// 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 Most of the time, your endpoints will return complete data, as in the `userAgent` example above. Sometimes, you may need to return a response that's too large to fit in memory in one go, or is delivered in chunks, and for this the platform provides [streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) — [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream), [WritableStream](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) and [TransformStream](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream). ## URL APIs URLs are represented by the [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) interface, which includes useful properties like `origin` and `pathname` (and, in the browser, `hash`). This interface shows up in various places — `event.url` in [hooks](hooks) and [server routes](routing#server), [`page.url`]($app-state) in [pages](routing#page), `from` and `to` in [`beforeNavigate` and `afterNavigate`]($app-navigation) and so on. ### URLSearchParams Wherever you encounter a URL, you can access query parameters via `url.searchParams`, which is an instance of [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams): ```js // @filename: ambient.d.ts declare global { const url: URL; } export {}; // @filename: index.js // ---cut--- const foo = url.searchParams.get('foo'); ``` ## Web Crypto The [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) is made available via the `crypto` global. It's used internally for [Content Security Policy](configuration#csp) headers, but you can also use it for things like generating UUIDs: ```js const uuid = crypto.randomUUID(); ```

# Routing

At the heart of SvelteKit is a _filesystem-based router_. The routes of your app — i.e. the URL paths that users can access — are defined by the directories in your codebase: - `src/routes` is the root route - `src/routes/about` creates an `/about` route - `src/routes/blog/[slug]` creates a route with a _parameter_, `slug`, that can be used to load data dynamically when a user requests a page like `/blog/hello-world` Each route directory contains one or more _route files_, which can be identified by their `+` prefix. We'll introduce these files in a moment in more detail, but here are a few simple rules to help you remember how SvelteKit's routing works: * All files can run on the server * All files run on the client except `+server` files * `+layout` and `+error` files apply to subdirectories as well as the directory they live in ## +page ### +page.svelte A `+page.svelte` component defines a page of your app. By default, pages are rendered both on the server ([SSR](glossary#SSR)) for the initial request and in the browser ([CSR](glossary#CSR)) for subsequent navigation. ```svelte <!--- file: src/routes/+page.svelte ---> <h1>Hello and welcome to my site!</h1> <a href="/about">About my site</a> ``` ```svelte <!--- file: src/routes/about/+page.svelte ---> <h1>About this site</h1> <p>TODO...</p> <a href="/">Home</a> ``` Pages can receive data from `load` functions via the `data` prop. ```svelte <!--- file: src/routes/blog/[slug]/+page.svelte ---> <script> /** @type {import('./$types').PageProps} */ let { data } = $props(); </script> <h1>{data.title}</h1> <div>{@html data.content}</div> ``` > `PageProps` was added in 2.16.0. In earlier versions, you had to type the `data` property manually with `PageData` instead, see [$types](#\$types). > > In Svelte 4, you'd use `export let data` instead. ### +page.js Often, a page will need to load some data before it can be rendered. For this, we add a `+page.js` module that exports a `load` function: ```js /// file: src/routes/blog/[slug]/+page.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'); } ``` This function runs alongside `+page.svelte`, which means it runs on the server during server-side rendering and in the browser during client-side navigation. See [`load`](load) for full details of the API. As well as `load`, `+page.js` can export values that configure the page's behaviour: - `export const prerender = true` or `false` or `'auto'` - `export const ssr = true` or `false` - `export const csr = true` or `false` You can find more information about these in [page options](page-options). ### +page.server.js If your `load` function can only run on the server — for example, if it needs to fetch data from a database or you need to access private [environment variables]($env-static-private) like API keys — then you can rename `+page.js` to `+page.server.js` and change the `PageLoad` type to `PageServerLoad`. ```js /// file: src/routes/blog/[slug]/+page.server.js // @filename: ambient.d.ts declare global { const getPostFromDatabase: (slug: string) => { title: string; content: string; } } export {}; // @filename: index.js // ---cut--- 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'); } ``` During client-side navigation, SvelteKit will load this data from the server, which means that the returned value must be serializable using [devalue](https://github.com/rich-harris/devalue). See [`load`](load) for full details of the API. Like `+page.js`, `+page.server.js` can export [page options](page-options) — `prerender`, `ssr` and `csr`. A `+page.server.js` file can also export _actions_. If `load` lets you read data from the server, `actions` let you write data _to_ the server using the `<form>` element. To learn how to use them, see the [form actions](form-actions) section. ## +error If an error occurs during `load`, SvelteKit will render a default error page. You can customise this error page on a per-route basis by adding an `+error.svelte` file: ```svelte <!--- file: src/routes/blog/[slug]/+error.svelte ---> <script> import { page } from '$app/state'; </script> <h1>{page.status}: {page.error.message}</h1> ``` > `$app/state` was added in SvelteKit 2.12. If you're using an earlier version or are using Svelte 4, use `$app/stores` instead. SvelteKit will 'walk up the tree' looking for the closest error boundary — if the file above didn't exist it would try `src/routes/blog/+error.svelte` and then `src/routes/+error.svelte` before rendering the default error page. If _that_ fails (or if the error was thrown from the `load` function of the root `+layout`, which sits 'above' the root `+error`), SvelteKit will bail out and render a static fallback error page, which you can customise by creating a `src/error.html` file. If the error occurs inside a `load` function in `+layout(.server).js`, the closest error boundary in the tree is an `+error.svelte` file _above_ that layout (not next to it). If no route can be found (404), `src/routes/+error.svelte` (or the default error page, if that file does not exist) will be used. You can read more about error handling [here](errors). ## +layout So far, we've treated pages as entirely standalone components — upon navigation, the existing `+page.svelte` component will be destroyed, and a new one will take its place. But in many apps, there are elements that should be visible on _every_ page, such as top-level navigation or a footer. Instead of repeating them in every `+page.svelte`, we can put them in _layouts_. ### +layout.svelte To create a layout that applies to every page, make a file called `src/routes/+layout.svelte`. The default layout (the one that SvelteKit uses if you don't bring your own) looks like this... ```svelte <script> let { children } = $props(); </script> {@render children()} ``` ...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a `@render` tag for the page content. For example, let's add a nav bar: ```svelte <!--- file: src/routes/+layout.svelte ---> <script> let { children } = $props(); </script> <nav> <a href="/">Home</a> <a href="/about">About</a> <a href="/settings">Settings</a> </nav> {@render children()} ``` If we create pages for `/`, `/about` and `/settings`... ```html /// file: src/routes/+page.svelte <h1>Home</h1> ``` ```html /// file: src/routes/about/+page.svelte <h1>About</h1> ``` ```html /// file: src/routes/settings/+page.svelte <h1>Settings</h1> ``` ...the nav will always be visible, and clicking between the three pages will only result in the `<h1>` being replaced. Layouts can be _nested_. Suppose we don't just have a single `/settings` page, but instead have nested pages like `/settings/profile` and `/settings/notifications` with a shared submenu (for a real-life example, see [github.com/settings](https://github.com/settings)). We can create a layout that only applies to pages below `/settings` (while inheriting the root layout with the top-level nav): ```svelte <!--- file: src/routes/settings/+layout.svelte ---> <script> /** @type {import('./$types').LayoutProps} */ let { data, children } = $props(); </script> <h1>Settings</h1> <div class="submenu"> {#each data.sections as section} <a href="/settings/{section.slug}">{section.title}</a> {/each} </div> {@render children()} ``` > `LayoutProps` was added in 2.16.0. In earlier versions, you had to [type the properties manually instead](#\$types). You can see how `data` is populated by looking at the `+layout.js` example in the next section just below. By default, each layout inherits the layout above it. Sometimes that isn't what you want - in this case, [advanced layouts](advanced-routing#Advanced-layouts) can help you. ### +layout.js Just like `+page.svelte` loading data from `+page.js`, your `+layout.svelte` component can get data from a [`load`](load) function in `+layout.js`. ```js /// file: src/routes/settings/+layout.js /** @type {import('./$types').LayoutLoad} */ export function load() { return { sections: [ { slug: 'profile', title: 'Profile' }, { slug: 'notifications', title: 'Notifications' } ] }; } ``` If a `+layout.js` exports [page options](page-options) — `prerender`, `ssr` and `csr` — they will be used as defaults for child pages. Data returned from a layout's `load` function is also available to all its child pages: ```svelte <!--- file: src/routes/settings/profile/+page.svelte ---> <script> /** @type {import('./$types').PageProps} */ let { data } = $props(); console.log(data.sections); // [{ slug: 'profile', title: 'Profile' }, ...] </script> ``` ### +layout.server.js To run your layout's `load` function on the server, move it to `+layout.server.js`, and change the `LayoutLoad` type to `LayoutServerLoad`. Like `+layout.js`, `+layout.server.js` can export [page options](page-options) — `prerender`, `ssr` and `csr`. ## +server As well as pages, you can define routes with a `+server.js` file (sometimes referred to as an 'API route' or an 'endpoint'), which gives you full control over the response. Your `+server.js` file exports functions corresponding to HTTP verbs like `GET`, `POST`, `PATCH`, `PUT`, `DELETE`, `OPTIONS`, and `HEAD` that take a `RequestEvent` argument and return a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object. For example we could create an `/api/random-number` route with a `GET` handler: ```js /// file: src/routes/api/random-number/+server.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)); } ``` The first argument to `Response` can be a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream), making it possible to stream large amounts of data or create server-sent events (unless deploying to platforms that buffer responses, like AWS Lambda). You can use the [`error`](@sveltejs-kit#error), [`redirect`](@sveltejs-kit#redirect) and [`json`](@sveltejs-kit#json) methods from `@sveltejs/kit` for convenience (but you don't have to). If an error is thrown (either `error(...)` or an unexpected error), the response will be a JSON representation of the error or a fallback error page — which can be customised via `src/error.html` — depending on the `Accept` header. The [`+error.svelte`](#error) component will _not_ be rendered in this case. You can read more about error handling [here](errors). ### Receiving data By exporting `POST`/`PUT`/`PATCH`/`DELETE`/`OPTIONS`/`HEAD` handlers, `+server.js` files can be used to create a complete API: ```svelte <!--- file: src/routes/add/+page.svelte ---> <script> let a = 0; let b = 0; let total = 0; async function add() { const response = await fetch('/api/add', { method: 'POST', body: JSON.stringify({ a, b }), headers: { 'content-type': 'application/json' } }); total = await response.json(); } </script> <input type="number" bind:value={a}> + <input type="number" bind:value={b}> = {total} <button onclick={add}>Calculate</button> ``` ```js /// file: src/routes/api/add/+server.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 method handler Exporting the `fallback` handler will match any unhandled request methods, including methods like `MOVE` which have no dedicated export from `+server.js`. ```js // @errors: 7031 /// file: src/routes/api/add/+server.js import { json, text } from '@sveltejs/kit'; export async function POST({ request }) { const { a, b } = await request.json(); return json(a + b); } // This handler will respond to PUT, PATCH, DELETE, etc. /** @type {import('./$types').RequestHandler} */ export async function fallback({ request }) { return text(`I caught your ${request.method} request!`); } ``` ### Content negotiation `+server.js` files can be placed in the same directory as `+page` files, allowing the same route to be either a page or an API endpoint. To determine which, SvelteKit applies the following rules: - `PUT`/`PATCH`/`DELETE`/`OPTIONS` requests are always handled by `+server.js` since they do not apply to pages - `GET`/`POST`/`HEAD` requests are treated as page requests if the `accept` header prioritises `text/html` (in other words, it's a browser page request), else they are handled by `+server.js`. - Responses to `GET` requests will include a `Vary: Accept` header, so that proxies and browsers cache HTML and JSON responses separately. ## $types Throughout the examples above, we've been importing types from a `$types.d.ts` file. This is a file SvelteKit creates for you in a hidden directory if you're using TypeScript (or JavaScript with JSDoc type annotations) to give you type safety when working with your root files. For example, annotating `let { data } = $props()` with `PageProps` (or `LayoutProps`, for a `+layout.svelte` file) tells TypeScript that the type of `data` is whatever was returned from `load`: ```svelte <!--- file: src/routes/blog/[slug]/+page.svelte ---> <script> /** @type {import('./$types').PageProps} */ let { data } = $props(); </script> ``` > The `PageProps` and `LayoutProps` types, added in 2.16.0, are a shortcut for typing the `data` prop as `PageData` or `LayoutData`, as well as other props, such as `form` for pages, or `children` for layouts. In earlier versions, you had to type these properties manually. For example, for a page: > > ```js > /// file: +page.svelte > /** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */ > let { data, form } = $props(); > ``` > > Or, for a layout: > > ```js > /// file: +layout.svelte > /** @type {{ data: import('./$types').LayoutData, children: Snippet }} */ > let { data, children } = $props(); > ``` In turn, annotating the `load` function with `PageLoad`, `PageServerLoad`, `LayoutLoad` or `LayoutServerLoad` (for `+page.js`, `+page.server.js`, `+layout.js` and `+layout.server.js` respectively) ensures that `params` and the return value are correctly typed. If you're using VS Code or any IDE that supports the language server protocol and TypeScript plugins then you can omit these types _entirely_! Svelte's IDE tooling will insert the correct types for you, so you'll get type checking without writing them yourself. It also works with our command line tool `svelte-check`. You can read more about omitting `$types` in our [blog post](/blog/zero-config-type-safety) about it. ## Other files Any other files inside a route directory are ignored by SvelteKit. This means you can colocate components and utility modules with the routes that need them. If components and modules are needed by multiple routes, it's a good idea to put them in [`$lib`]($lib). ## Further reading - [Tutorial: Routing](/tutorial/kit/pages) - [Tutorial: API routes](/tutorial/kit/get-handlers) - [Docs: Advanced routing](advanced-routing)

# Loading data

Before a [`+page.svelte`](routing#page-page.svelte) component (and its containing [`+layout.svelte`](routing#layout-layout.svelte) components) can be rendered, we often need to get some data. This is done by defining `load` functions. ## Page data A `+page.svelte` file can have a sibling `+page.js` that exports a `load` function, the return value of which is available to the page via the `data` prop: ```js /// file: src/routes/blog/[slug]/+page.js /** @type {import('./$types').PageLoad} */ export function load({ params }) { return { post: { title: `Title for ${params.slug} goes here`, content: `Content for ${params.slug} goes here` } }; } ``` ```svelte <!--- file: src/routes/blog/[slug]/+page.svelte ---> <script> /** @type {import('./$types').PageProps} */ let { data } = $props(); </script> <h1>{data.post.title}</h1> <div>{@html data.post.content}</div> ``` > Before version 2.16.0, the props of a page and layout had to be typed individually: > ```js > /// file: +page.svelte > /** @type {{ data: import('./$types').PageData }} */ > let { data } = $props(); > ``` > > In Svelte 4, you'd use `export let data` instead. Thanks to the generated `$types` module, we get full type safety. A `load` function in a `+page.js` file runs both on the server and in the browser (unless combined with `export const ssr = false`, in which case it will [only run in the browser](page-options#ssr)). If your `load` function should _always_ run on the server (because it uses private environment variables, for example, or accesses a database) then it would go in a `+page.server.js` instead. A more realistic version of your blog post's `load` function, that only runs on the server and pulls data from a database, might look like this: ```js /// file: src/routes/blog/[slug]/+page.server.js // @filename: ambient.d.ts declare module '$lib/server/database' { export function getPost(slug: string): Promise<{ title: string, content: string }> } // @filename: index.js // ---cut--- import * as db from '$lib/server/database'; /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { return { post: await db.getPost(params.slug) }; } ``` Notice that the type changed from `PageLoad` to `PageServerLoad`, because server `load` functions can access additional arguments. To understand when to use `+page.js` and when to use `+page.server.js`, see [Universal vs server](load#Universal-vs-server). ## Layout data Your `+layout.svelte` files can also load data, via `+layout.js` or `+layout.server.js`. ```js /// file: src/routes/blog/[slug]/+layout.server.js // @filename: ambient.d.ts declare module '$lib/server/database' { export function getPostSummaries(): Promise<Array<{ title: string, slug: string }>> } // @filename: index.js // ---cut--- import * as db from '$lib/server/database'; /** @type {import('./$types').LayoutServerLoad} */ export async function load() { return { posts: await db.getPostSummaries() }; } ``` ```svelte <!--- file: src/routes/blog/[slug]/+layout.svelte ---> <script> /** @type {import('./$types').LayoutProps} */ let { data, children } = $props(); </script> <main> <!-- +page.svelte is `@render`ed here --> {@render children()} </main> <aside> <h2>More posts</h2> <ul> {#each data.posts as post} <li> <a href="/blog/{post.slug}"> {post.title} </a> </li> {/each} </ul> </aside> ``` > `LayoutProps` was added in 2.16.0. In earlier versions, properties had to be typed individually: > ```js > /// file: +layout.svelte > /** @type {{ data: import('./$types').LayoutData, children: Snippet }} */ > let { data, children } = $props(); > ``` Data returned from layout `load` functions is available to child `+layout.svelte` components and the `+page.svelte` component as well as the layout that it 'belongs' to. ```svelte /// file: src/routes/blog/[slug]/+page.svelte <script> +++import { page } from '$app/state';+++ /** @type {import('./$types').PageProps} */ let { data } = $props(); +++ // we can access `data.posts` because it's returned from // the parent layout `load` function let index = $derived(data.posts.findIndex(post => post.slug === page.params.slug)); let next = $derived(data.posts[index + 1]);+++ </script> <h1>{data.post.title}</h1> <div>{@html data.post.content}</div> +++{#if next} <p>Next post: <a href="/blog/{next.slug}">{next.title}</a></p> {/if}+++ ``` ## page.data The `+page.svelte` component, and each `+layout.svelte` component above it, has access to its own data plus all the data from its parents. In some cases, we might need the opposite — a parent layout might need to access page data or data from a child layout. For example, the root layout might want to access a `title` property returned from a `load` function in `+page.js` or `+page.server.js`. This can be done with `page.data`: ```svelte <!--- file: src/routes/+layout.svelte ---> <script> import { page } from '$app/state'; </script> <svelte:head> <title>{page.data.title}</title> </svelte:head> ``` Type information for `page.data` is provided by `App.PageData`. > `$app/state` was added in SvelteKit 2.12. If you're using an earlier version or are using Svelte 4, use `$app/stores` instead. > It provides a `page` store with the same interface that you can subscribe to, e.g. `$page.data.title`. ## Universal vs server As we've seen, there are two types of `load` function: * `+page.js` and `+layout.js` files export _universal_ `load` functions that run both on the server and in the browser * `+page.server.js` and `+layout.server.js` files export _server_ `load` functions that only run server-side Conceptually, they're the same thing, but there are some important differences to be aware of. ### When does which load function run? Server `load` functions _always_ run on the server. By default, universal `load` functions run on the server during SSR when the user first visits your page. They will then run again during hydration, reusing any responses from [fetch requests](#Making-fetch-requests). All subsequent invocations of universal `load` functions happen in the browser. You can customize the behavior through [page options](page-options). If you disable [server side rendering](page-options#ssr), you'll get an SPA and universal `load` functions _always_ run on the client. If a route contains both universal and server `load` functions, the server `load` runs first. A `load` function is invoked at runtime, unless you [prerender](page-options#prerender) the page — in that case, it's invoked at build time. ### Input Both universal and server `load` functions have access to properties describing the request (`params`, `route` and `url`) and various functions (`fetch`, `setHeaders`, `parent`, `depends` and `untrack`). These are described in the following sections. Server `load` functions are called with a `ServerLoadEvent`, which inherits `clientAddress`, `cookies`, `locals`, `platform` and `request` from `RequestEvent`. Universal `load` functions are called with a `LoadEvent`, which has a `data` property. If you have `load` functions in both `+page.js` and `+page.server.js` (or `+layout.js` and `+layout.server.js`), the return value of the server `load` function is the `data` property of the universal `load` function's argument. ### Output A universal `load` function can return an object containing any values, including things like custom classes and component constructors. A server `load` function must return data that can be serialized with [devalue](https://github.com/rich-harris/devalue) — anything that can be represented as JSON plus things like `BigInt`, `Date`, `Map`, `Set` and `RegExp`, or repeated/cyclical references — so that it can be transported over the network. Your data can include [promises](#Streaming-with-promises), in which case it will be streamed to browsers. ### When to use which Server `load` functions are convenient when you need to access data directly from a database or filesystem, or need to use private environment variables. Universal `load` functions are useful when you need to `fetch` data from an external API and don't need private credentials, since SvelteKit can get the data directly from the API rather than going via your server. They are also useful when you need to return something that can't be serialized, such as a Svelte component constructor. In rare cases, you might need to use both together — for example, you might need to return an instance of a custom class that was initialised with data from your server. When using both, the server `load` return value is _not_ passed directly to the page, but to the universal `load` function (as the `data` property): ```js /// file: src/routes/+page.server.js /** @type {import('./$types').PageServerLoad} */ export async function load() { return { serverMessage: 'hello from server load function' }; } ``` ```js /// file: src/routes/+page.js // @errors: 18047 /** @type {import('./$types').PageLoad} */ export async function load({ data }) { return { serverMessage: data.serverMessage, universalMessage: 'hello from universal load function' }; } ``` ## Using URL data Often the `load` function depends on the URL in one way or another. For this, the `load` function provides you with `url`, `route` and `params`. ### url An instance of [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL), containing properties like the `origin`, `hostname`, `pathname` and `searchParams` (which contains the parsed query string as a [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) object). `url.hash` cannot be accessed during `load`, since it is unavailable on the server. ### route Contains the name of the current route directory, relative to `src/routes`: ```js /// file: src/routes/a/[b]/[...c]/+page.js /** @type {import('./$types').PageLoad} */ export function load({ route }) { console.log(route.id); // '/a/[b]/[...c]' } ``` ### params `params` is derived from `url.pathname` and `route.id`. Given a `route.id` of `/a/[b]/[...c]` and a `url.pathname` of `/a/x/y/z`, the `params` object would look like this: ```json { "b": "x", "c": "y/z" } ``` ## Making fetch requests To get data from an external API or a `+server.js` handler, you can use the provided `fetch` function, which behaves identically to the [native `fetch` web API](https://developer.mozilla.org/en-US/docs/Web/API/fetch) with a few additional features: - It can be used to make credentialed requests on the server, as it inherits the `cookie` and `authorization` headers for the page request. - It can make relative requests on the server (ordinarily, `fetch` requires a URL with an origin when used in a server context). - Internal requests (e.g. for `+server.js` routes) go directly to the handler function when running on the server, without the overhead of an HTTP call. - During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the `text`, `json` and `arrayBuffer` methods of the `Response` object. Note that headers will _not_ be serialized, unless explicitly included via [`filterSerializedResponseHeaders`](hooks#Server-hooks-handle). - During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request - if you received a warning in your browser console when using the browser `fetch` instead of the `load` `fetch`, this is why. ```js /// file: src/routes/items/[id]/+page.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 A server `load` function can get and set [`cookies`](@sveltejs-kit#Cookies). ```js /// file: src/routes/+layout.server.js // @filename: ambient.d.ts declare module '$lib/server/database' { export function getUser(sessionid: string | undefined): Promise<{ name: string, avatar: string }> } // @filename: index.js // ---cut--- import * as db from '$lib/server/database'; /** @type {import('./$types').LayoutServerLoad} */ export async function load({ cookies }) { const sessionid = cookies.get('sessionid'); return { user: await db.getUser(sessionid) }; } ``` Cookies will only be passed through the provided `fetch` function if the target host is the same as the SvelteKit application or a more specific subdomain of it. For example, if SvelteKit is serving my.domain.com: - domain.com WILL NOT receive cookies - my.domain.com WILL receive cookies - api.domain.com WILL NOT receive cookies - sub.my.domain.com WILL receive cookies Other cookies will not be passed when `credentials: 'include'` is set, because SvelteKit does not know which domain which cookie belongs to (the browser does not pass this information along), so it's not safe to forward any of them. Use the [handleFetch hook](hooks#Server-hooks-handleFetch) to work around it. ## Headers Both server and universal `load` functions have access to a `setHeaders` function that, when running on the server, can set headers for the response. (When running in the browser, `setHeaders` has no effect.) This is useful if you want the page to be cached, for example: ```js // @errors: 2322 1360 /// file: src/routes/products/+page.js /** @type {import('./$types').PageLoad} */ export async function load({ fetch, setHeaders }) { const url = `https://cms.example.com/products.json`; const response = await fetch(url); // Headers are only set during SSR, caching the page's HTML // for the same length of time as the underlying data. setHeaders({ age: response.headers.get('age'), 'cache-control': response.headers.get('cache-control') }); return response.json(); } ``` Setting the same header multiple times (even in separate `load` functions) is an error. You can only set a given header once using the `setHeaders` function. You cannot add a `set-cookie` header with `setHeaders` — use `cookies.set(name, value, options)` instead. ## Using parent data Occasionally it's useful for a `load` function to access data from a parent `load` function, which can be done with `await parent()`: ```js /// file: src/routes/+layout.js /** @type {import('./$types').LayoutLoad} */ export function load() { return { a: 1 }; } ``` ```js /// file: src/routes/abc/+layout.js /** @type {import('./$types').LayoutLoad} */ export async function load({ parent }) { const { a } = await parent(); return { b: a + 1 }; } ``` ```js /// file: src/routes/abc/+page.js /** @type {import('./$types').PageLoad} */ export async function load({ parent }) { const { a, b } = await parent(); return { c: a + b }; } ``` ```svelte <!--- file: src/routes/abc/+page.svelte ---> <script> /** @type {import('./$types').PageProps} */ let { data } = $props(); </script> <!-- renders `1 + 2 = 3` --> <p>{data.a} + {data.b} = {data.c}</p> ``` Inside `+page.server.js` and `+layout.server.js`, `parent` returns data from parent `+layout.server.js` files. In `+page.js` or `+layout.js` it will return data from parent `+layout.js` files. However, a missing `+layout.js` is treated as a `({ data }) => data` function, meaning that it will also return data from parent `+layout.server.js` files that are not 'shadowed' by a `+layout.js` file Take care not to introduce waterfalls when using `await parent()`. Here, for example, `getData(params)` does not depend on the result of calling `parent()`, so we should call it first to avoid a delayed render. ```js /// file: +page.js // @filename: ambient.d.ts declare function getData(params: Record<string, string>): Promise<{ meta: any }> // @filename: index.js // ---cut--- /** @type {import('./$types').PageLoad} */ export async function load({ params, parent }) { ---const parentData = await parent();--- const data = await getData(params); +++const parentData = await parent();+++ return { ...data, meta: { ...parentData.meta, ...data.meta } }; } ``` ## Errors If an error is thrown during `load`, the nearest [`+error.svelte`](routing#error) will be rendered. For [_expected_](errors#Expected-errors) errors, use the `error` helper from `@sveltejs/kit` to specify the HTTP status code and an optional message: ```js /// file: src/routes/admin/+layout.server.js // @filename: ambient.d.ts declare namespace App { interface Locals { user?: { name: string; isAdmin: boolean; } } } // @filename: index.js // ---cut--- import { error } from '@sveltejs/kit'; /** @type {import('./$types').LayoutServerLoad} */ export function load({ locals }) { if (!locals.user) { error(401, 'not logged in'); } if (!locals.user.isAdmin) { error(403, 'not an admin'); } } ``` Calling `error(...)` will throw an exception, making it easy to stop execution from inside helper functions. If an [_unexpected_](errors#Unexpected-errors) error is thrown, SvelteKit will invoke [`handleError`](hooks#Shared-hooks-handleError) and treat it as a 500 Internal Error. ## Redirects To redirect users, use the `redirect` helper from `@sveltejs/kit` to specify the location to which they should be redirected alongside a `3xx` status code. Like `error(...)`, calling `redirect(...)` will throw an exception, making it easy to stop execution from inside helper functions. ```js /// file: src/routes/user/+layout.server.js // @filename: ambient.d.ts declare namespace App { interface Locals { user?: { name: string; } } } // @filename: index.js // ---cut--- import { redirect } from '@sveltejs/kit'; /** @type {import('./$types').LayoutServerLoad} */ export function load({ locals }) { if (!locals.user) { redirect(307, '/login'); } } ``` In the browser, you can also navigate programmatically outside of a `load` function using [`goto`]($app-navigation#goto) from [`$app.navigation`]($app-navigation). ## Streaming with promises When using a server `load`, promises will be streamed to the browser as they resolve. This is useful if you have slow, non-essential data, since you can start rendering the page before all the data is available: ```js /// file: src/routes/blog/[slug]/+page.server.js // @filename: ambient.d.ts declare global { const loadPost: (slug: string) => Promise<{ title: string, content: string }>; const loadComments: (slug: string) => Promise<{ content: string }>; } export {}; // @filename: index.js // ---cut--- /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { return { // make sure the `await` happens at the end, otherwise we // can't start loading comments until we've loaded the post comments: loadComments(params.slug), post: await loadPost(params.slug) }; } ``` This is useful for creating skeleton loading states, for example: ```svelte <!--- file: src/routes/blog/[slug]/+page.svelte ---> <script> /** @type {import('./$types').PageProps} */ let { data } = $props(); </script> <h1>{data.post.title}</h1> <div>{@html data.post.content}</div> {#await data.comments} Loading comments... {:then comments} {#each comments as comment} <p>{comment.content}</p> {/each} {:catch error} <p>error loading comments: {error.message}</p> {/await} ``` When streaming data, be careful to handle promise rejections correctly. More specifically, the server could crash with an "unhandled promise rejection" error if a lazy-loaded promise fails before rendering starts (at which point it's caught) and isn't handling the error in some way. When using SvelteKit's `fetch` directly in the `load` function, SvelteKit will handle this case for you. For other promises, it is enough to attach a noop-`catch` to the promise to mark it as handled. ```js /// file: src/routes/+page.server.js /** @type {import('./$types').PageServerLoad} */ export function load({ fetch }) { const ok_manual = Promise.reject(); ok_manual.catch(() => {}); return { ok_manual, ok_fetch: fetch('/fetch/that/could/fail'), dangerous_unhandled: Promise.reject() }; } ``` ## Parallel loading When rendering (or navigating to) a page, SvelteKit runs all `load` functions concurrently, avoiding a waterfall of requests. During client-side navigation, the result of calling multiple server `load` functions are grouped into a single response. Once all `load` functions have returned, the page is rendered. ## Rerunning load functions SvelteKit tracks the dependencies of each `load` function to avoid rerunning it unnecessarily during navigation. For example, given a pair of `load` functions like these... ```js /// file: src/routes/blog/[slug]/+page.server.js // @filename: ambient.d.ts declare module '$lib/server/database' { export function getPost(slug: string): Promise<{ title: string, content: string }> } // @filename: index.js // ---cut--- import * as db from '$lib/server/database'; /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { return { post: await db.getPost(params.slug) }; } ``` ```js /// file: src/routes/blog/[slug]/+layout.server.js // @filename: ambient.d.ts declare module '$lib/server/database' { export function getPostSummaries(): Promise<Array<{ title: string, slug: string }>> } // @filename: index.js // ---cut--- import * as db from '$lib/server/database'; /** @type {import('./$types').LayoutServerLoad} */ export async function load() { return { posts: await db.getPostSummaries() }; } ``` ...the one in `+page.server.js` will rerun if we navigate from `/blog/trying-the-raw-meat-diet` to `/blog/i-regret-my-choices` because `params.slug` has changed. The one in `+layout.server.js` will not, because the data is still valid. In other words, we won't call `db.getPostSummaries()` a second time. A `load` function that calls `await parent()` will also rerun if a parent `load` function is rerun. Dependency tracking does not apply _after_ the `load` function has returned — for example, accessing `params.x` inside a nested [promise](#Streaming-with-promises) will not cause the function to rerun when `params.x` changes. (Don't worry, you'll get a warning in development if you accidentally do this.) Instead, access the parameter in the main body of your `load` function. Search parameters are tracked independently from the rest of the url. For example, accessing `event.url.searchParams.get("x")` inside a `load` function will make that `load` function re-run when navigating from `?x=1` to `?x=2`, but not when navigating from `?x=1&y=1` to `?x=1&y=2`. ### Untracking dependencies In rare cases, you may wish to exclude something from the dependency tracking mechanism. You can do this with the provided `untrack` function: ```js /// file: src/routes/+page.js /** @type {import('./$types').PageLoad} */ export async function load({ untrack, url }) { // Untrack url.pathname so that path changes don't trigger a rerun if (untrack(() => url.pathname === '/')) { return { message: 'Welcome!' }; } } ``` ### Manual invalidation You can also rerun `load` functions that apply to the current page using [`invalidate(url)`]($app-navigation#invalidate), which reruns all `load` functions that depend on `url`, and [`invalidateAll()`]($app-navigation#invalidateAll), which reruns every `load` function. Server load functions will never automatically depend on a fetched `url` to avoid leaking secrets to the client. A `load` function depends on `url` if it calls `fetch(url)` or `depends(url)`. Note that `url` can be a custom identifier that starts with `[a-z]:`: ```js /// file: src/routes/random-number/+page.js /** @type {import('./$types').PageLoad} */ export async function load({ fetch, depends }) { // load reruns when `invalidate('https://api.example.com/random-number')` is called... const response = await fetch('https://api.example.com/random-number'); // ...or when `invalidate('app:random')` is called depends('app:random'); return { number: await response.json() }; } ``` ```svelte <!--- file: src/routes/random-number/+page.svelte ---> <script> import { invalidate, invalidateAll } from '$app/navigation'; /** @type {import('./$types').PageProps} */ let { data } = $props(); function rerunLoadFunction() { // any of these will cause the `load` function to rerun invalidate('app:random'); invalidate('https://api.example.com/random-number'); invalidate(url => url.href.includes('random-number')); invalidateAll(); } </script> <p>random number: {data.number}</p> <button onclick={rerunLoadFunction}>Update random number</button> ``` ### When do load functions rerun? To summarize, a `load` function will rerun in the following situations: - It references a property of `params` whose value has changed - It references a property of `url` (such as `url.pathname` or `url.search`) whose value has changed. Properties in `request.url` are _not_ tracked - It calls `url.searchParams.get(...)`, `url.searchParams.getAll(...)` or `url.searchParams.has(...)` and the parameter in question changes. Accessing other properties of `url.searchParams` will have the same effect as accessing `url.search`. - It calls `await parent()` and a parent `load` function reran - A child `load` function calls `await parent()` and is rerunning, and the parent is a server load function - It declared a dependency on a specific URL via [`fetch`](#Making-fetch-requests) (universal load only) or [`depends`](@sveltejs-kit#LoadEvent), and that URL was marked invalid with [`invalidate(url)`]($app-navigation#invalidate) - All active `load` functions were forcibly rerun with [`invalidateAll()`]($app-navigation#invalidateAll) `params` and `url` can change in response to a `<a href="..">` link click, a [`<form>` interaction](form-actions#GET-vs-POST), a [`goto`]($app-navigation#goto) invocation, or a [`redirect`](@sveltejs-kit#redirect). Note that rerunning a `load` function will update the `data` prop inside the corresponding `+layout.svelte` or `+page.svelte`; it does _not_ cause the component to be recreated. As a result, internal state is preserved. If this isn't what you want, you can reset whatever you need to reset inside an [`afterNavigate`]($app-navigation#afterNavigate) callback, and/or wrap your component in a [`{#key ...}`](../svelte/key) block. ## Implications for authentication A couple features of loading data have important implications for auth checks: - Layout `load` functions do not run on every request, such as during client side navigation between child routes. [(When do load functions rerun?)](load#Rerunning-load-functions-When-do-load-functions-rerun) - Layout and page `load` functions run concurrently unless `await parent()` is called. If a layout `load` throws, the page `load` function runs, but the client will not receive the returned data. There are a few possible strategies to ensure an auth check occurs before protected code. To prevent data waterfalls and preserve layout `load` caches: - Use [hooks](hooks) to protect multiple routes before any `load` functions run - Use auth guards directly in `+page.server.js` `load` functions for route specific protection Putting an auth guard in `+layout.server.js` requires all child pages to call `await parent()` before protected code. Unless every child page depends on returned data from `await parent()`, the other options will be more performant. ## Further reading - [Tutorial: Loading data](/tutorial/kit/page-data) - [Tutorial: Errors and redirects](/tutorial/kit/error-basics) - [Tutorial: Advanced loading](/tutorial/kit/await-parent)

# Form actions

A `+page.server.js` file can export _actions_, which allow you to `POST` data to the server using the `<form>` element. When using `<form>`, client-side JavaScript is optional, but you can easily _progressively enhance_ your form interactions with JavaScript to provide the best user experience. ## Default actions In the simplest case, a page declares a `default` action: ```js /// file: src/routes/login/+page.server.js /** @satisfies {import('./$types').Actions} */ export const actions = { default: async (event) => { // TODO log the user in } }; ``` To invoke this action from the `/login` page, just add a `<form>` — no JavaScript needed: ```svelte <!--- file: src/routes/login/+page.svelte ---> <form method="POST"> <label> Email <input name="email" type="email"> </label> <label> Password <input name="password" type="password"> </label> <button>Log in</button> </form> ``` If someone were to click the button, the browser would send the form data via `POST` request to the server, running the default action. We can also invoke the action from other pages (for example if there's a login widget in the nav in the root layout) by adding the `action` attribute, pointing to the page: ```html /// file: src/routes/+layout.svelte <form method="POST" action="/login"> <!-- content --> </form> ``` ## Named actions Instead of one `default` action, a page can have as many named actions as it needs: ```js /// file: src/routes/login/+page.server.js /** @satisfies {import('./$types').Actions} */ export const actions = { --- default: async (event) => {--- +++ login: async (event) => {+++ // TODO log the user in }, +++ register: async (event) => { // TODO register the user }+++ }; ``` To invoke a named action, add a query parameter with the name prefixed by a `/` character: ```svelte <!--- file: src/routes/login/+page.svelte ---> <form method="POST" action="?/register"> ``` ```svelte <!--- file: src/routes/+layout.svelte ---> <form method="POST" action="/login?/register"> ``` As well as the `action` attribute, we can use the `formaction` attribute on a button to `POST` the same form data to a different action than the parent `<form>`: ```svelte /// file: src/routes/login/+page.svelte <form method="POST" +++action="?/login"+++> <label> Email <input name="email" type="email"> </label> <label> Password <input name="password" type="password"> </label> <button>Log in</button> +++<button formaction="?/register">Register</button>+++ </form> ``` ## Anatomy of an action Each action receives a `RequestEvent` object, allowing you to read the data with `request.formData()`. After processing the request (for example, logging the user in by setting a cookie), the action can respond with data that will be available through the `form` property on the corresponding page and through `page.form` app-wide until the next update. ```js /// file: src/routes/login/+page.server.js // @filename: ambient.d.ts declare module '$lib/server/db'; // @filename: index.js // ---cut--- import * as db from '$lib/server/db'; /** @type {import('./$types').PageServerLoad} */ export async function load({ cookies }) { const user = await db.getUserFromSession(cookies.get('sessionid')); return { user }; } /** @satisfies {import('./$types').Actions} */ 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 }; }, register: async (event) => { // TODO register the user } }; ``` ```svelte <!--- file: src/routes/login/+page.svelte ---> <script> /** @type {import('./$types').PageProps} */ let { data, form } = $props(); </script> {#if form?.success} <!-- this message is ephemeral; it exists because the page was rendered in response to a form submission. it will vanish if the user reloads --> <p>Successfully logged in! Welcome back, {data.user.name}</p> {/if} ``` > `PageProps` was added in 2.16.0. In earlier versions, you had to type the `data` and `form` properties individually: > ```js > /// file: +page.svelte > /** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */ > let { data, form } = $props(); > ``` > > In Svelte 4, you'd use `export let data` and `export let form` instead to declare properties. ### Validation errors If the request couldn't be processed because of invalid data, you can return validation errors — along with the previously submitted form values — back to the user so that they can try again. The `fail` function lets you return an HTTP status code (typically 400 or 422, in the case of validation errors) along with the data. The status code is available through `page.status` and the data through `form`: ```js /// file: src/routes/login/+page.server.js // @filename: ambient.d.ts declare module '$lib/server/db'; // @filename: index.js // ---cut--- +++import { fail } from '@sveltejs/kit';+++ import * as db from '$lib/server/db'; /** @satisfies {import('./$types').Actions} */ 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 }); }+++ cookies.set('sessionid', await db.createSession(user), { path: '/' }); return { success: true }; }, register: async (event) => { // TODO register the user } }; ``` ```svelte /// file: src/routes/login/+page.svelte <form method="POST" action="?/login"> +++ {#if form?.missing}<p class="error">The email field is required</p>{/if} {#if form?.incorrect}<p class="error">Invalid credentials!</p>{/if}+++ <label> Email <input name="email" type="email" +++value={form?.email ?? ''}+++> </label> <label> Password <input name="password" type="password"> </label> <button>Log in</button> <button formaction="?/register">Register</button> </form> ``` The returned data must be serializable as JSON. Beyond that, the structure is entirely up to you. For example, if you had multiple forms on the page, you could distinguish which `<form>` the returned `form` data referred to with an `id` property or similar. ### Redirects Redirects (and errors) work exactly the same as in [`load`](load#Redirects): ```js // @errors: 2345 /// file: src/routes/login/+page.server.js // @filename: ambient.d.ts declare module '$lib/server/db'; // @filename: index.js // ---cut--- import { fail, +++redirect+++ } from '@sveltejs/kit'; import * as db from '$lib/server/db'; /** @satisfies {import('./$types').Actions} */ export const actions = { login: async ({ cookies, request, +++url+++ }) => { const data = await request.formData(); const email = data.get('email'); const password = data.get('password'); const user = await db.getUser(email); if (!user) { return fail(400, { email, missing: true }); } if (user.password !== db.hash(password)) { return fail(400, { email, incorrect: true }); } cookies.set('sessionid', await db.createSession(user), { path: '/' }); +++ if (url.searchParams.has('redirectTo')) { redirect(303, url.searchParams.get('redirectTo')); }+++ return { success: true }; }, register: async (event) => { // TODO register the user } }; ``` ## Loading data After an action runs, the page will be re-rendered (unless a redirect or an unexpected error occurs), with the action's return value available to the page as the `form` prop. This means that your page's `load` functions will run after the action completes. Note that `handle` runs before the action is invoked, and does not rerun before the `load` functions. This means that if, for example, you use `handle` to populate `event.locals` based on a cookie, you must update `event.locals` when you set or delete the cookie in an action: ```js /// file: src/hooks.server.js // @filename: ambient.d.ts declare namespace App { interface Locals { user: { name: string; } | null } } // @filename: global.d.ts declare global { function getUser(sessionid: string | undefined): { name: string; }; } export {}; // @filename: index.js // ---cut--- /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { event.locals.user = await getUser(event.cookies.get('sessionid')); return resolve(event); } ``` ```js /// file: src/routes/account/+page.server.js // @filename: ambient.d.ts declare namespace App { interface Locals { user: { name: string; } | null } } // @filename: index.js // ---cut--- /** @type {import('./$types').PageServerLoad} */ export function load(event) { return { user: event.locals.user }; } /** @satisfies {import('./$types').Actions} */ export const actions = { logout: async (event) => { event.cookies.delete('sessionid', { path: '/' }); event.locals.user = null; } }; ``` ## Progressive enhancement In the preceding sections we built a `/login` action that [works without client-side JavaScript](https://kryogenix.org/code/browser/everyonehasjs.html) — not a `fetch` in sight. That's great, but when JavaScript _is_ available we can progressively enhance our form interactions to provide a better user experience. ### use:enhance The easiest way to progressively enhance a form is to add the `use:enhance` action: ```svelte /// file: src/routes/login/+page.svelte <script> +++import { enhance } from '$app/forms';+++ /** @type {import('./$types').PageProps} */ let { form } = $props(); </script> <form method="POST" +++use:enhance+++> ``` Without an argument, `use:enhance` will emulate the browser-native behaviour, just without the full-page reloads. It will: - update the `form` property, `page.form` and `page.status` on a successful or invalid response, but only if the action is on the same page you're submitting from. For example, if your form looks like `<form action="/somewhere/else" ..>`, the `form` prop and the `page.form` state will _not_ be updated. This is because in the native form submission case you would be redirected to the page the action is on. If you want to have them updated either way, use [`applyAction`](#Progressive-enhancement-Customising-use:enhance) - reset the `<form>` element - invalidate all data using `invalidateAll` on a successful response - call `goto` on a redirect response - render the nearest `+error` boundary if an error occurs - [reset focus](accessibility#Focus-management) to the appropriate element ### Customising use:enhance To customise the behaviour, you can provide a `SubmitFunction` that runs immediately before the form is submitted, and (optionally) returns a callback that runs with the `ActionResult`. Note that if you return a callback, the default behavior mentioned above is not triggered. To get it back, call `update`. ```svelte <form method="POST" use:enhance={({ formElement, formData, action, cancel, submitter }) => { // `formElement` is this `<form>` element // `formData` is its `FormData` object that's about to be submitted // `action` is the URL to which the form is posted // calling `cancel()` will prevent the submission // `submitter` is the `HTMLElement` that caused the form to be submitted return async ({ result, update }) => { // `result` is an `ActionResult` object // `update` is a function which triggers the default logic that would be triggered if this callback wasn't set }; }} > ``` You can use these functions to show and hide loading UI, and so on. If you return a callback, you may need to reproduce part of the default `use:enhance` behaviour, but without invalidating all data on a successful response. You can do so with `applyAction`: ```svelte /// file: src/routes/login/+page.svelte <script> import { enhance, +++applyAction+++ } from '$app/forms'; /** @type {import('./$types').PageProps} */ let { form } = $props(); </script> <form method="POST" use:enhance={({ formElement, formData, action, cancel }) => { return async ({ result }) => { // `result` is an `ActionResult` object +++ if (result.type === 'redirect') { goto(result.location); } else { await applyAction(result); }+++ }; }} > ``` The behaviour of `applyAction(result)` depends on `result.type`: - `success`, `failure` — sets `page.status` to `result.status` and updates `form` and `page.form` to `result.data` (regardless of where you are submitting from, in contrast to `update` from `enhance`) - `redirect` — calls `goto(result.location, { invalidateAll: true })` - `error` — renders the nearest `+error` boundary with `result.error` In all cases, [focus will be reset](accessibility#Focus-management). ### Custom event listener We can also implement progressive enhancement ourselves, without `use:enhance`, with a normal event listener on the `<form>`: ```svelte <!--- file: src/routes/login/+page.svelte ---> <script> import { invalidateAll, goto } from '$app/navigation'; import { applyAction, deserialize } from '$app/forms'; /** @type {import('./$types').PageProps} */ let { form } = $props(); /** @param {SubmitEvent & { currentTarget: EventTarget & HTMLFormElement}} event */ async function handleSubmit(event) { event.preventDefault(); const data = new FormData(event.currentTarget); const response = await fetch(event.currentTarget.action, { method: 'POST', body: data }); /** @type {import('@sveltejs/kit').ActionResult} */ const result = deserialize(await response.text()); if (result.type === 'success') { // rerun all `load` functions, following the successful update await invalidateAll(); } applyAction(result); } </script> <form method="POST" onsubmit={handleSubmit}> <!-- content --> </form> ``` Note that you need to `deserialize` the response before processing it further using the corresponding method from `$app/forms`. `JSON.parse()` isn't enough because form actions - like `load` functions - also support returning `Date` or `BigInt` objects. If you have a `+server.js` alongside your `+page.server.js`, `fetch` requests will be routed there by default. To `POST` to an action in `+page.server.js` instead, use the custom `x-sveltekit-action` header: ```js const response = await fetch(this.action, { method: 'POST', body: data, +++ headers: { 'x-sveltekit-action': 'true' }+++ }); ``` ## Alternatives Form actions are the preferred way to send data to the server, since they can be progressively enhanced, but you can also use [`+server.js`](routing#server) files to expose (for example) a JSON API. Here's how such an interaction could look like: ```svelte <!--- file: src/routes/send-message/+page.svelte ---> <script> function rerun() { fetch('/api/ci', { method: 'POST' }); } </script> <button onclick={rerun}>Rerun CI</button> ``` ```js // @errors: 2355 1360 2322 /// file: src/routes/api/ci/+server.js /** @type {import('./$types').RequestHandler} */ export function POST() { // do something } ``` ## GET vs POST As we've seen, to invoke a form action you must use `method="POST"`. Some forms don't need to `POST` data to the server — search inputs, for example. For these you can use `method="GET"` (or, equivalently, no `method` at all), and SvelteKit will treat them like `<a>` elements, using the client-side router instead of a full page navigation: ```html <form action="/search"> <label> Search <input name="q"> </label> </form> ``` Submitting this form will navigate to `/search?q=...` and invoke your load function but will not invoke an action. As with `<a>` elements, you can set the [`data-sveltekit-reload`](link-options#data-sveltekit-reload), [`data-sveltekit-replacestate`](link-options#data-sveltekit-replacestate), [`data-sveltekit-keepfocus`](link-options#data-sveltekit-keepfocus) and [`data-sveltekit-noscroll`](link-options#data-sveltekit-noscroll) attributes on the `<form>` to control the router's behaviour. ## Further reading - [Tutorial: Forms](/tutorial/kit/the-form-element)

# Page options

By default, SvelteKit will render (or [prerender](glossary#Prerendering)) any component first on the server and send it to the client as HTML. It will then render the component again in the browser to make it interactive in a process called [**hydration**](glossary#Hydration). For this reason, you need to ensure that components can run in both places. SvelteKit will then initialize a [**router**](routing) that takes over subsequent navigations. You can control each of these on a page-by-page basis by exporting options from [`+page.js`](routing#page-page.js) or [`+page.server.js`](routing#page-page.server.js), or for groups of pages using a shared [`+layout.js`](routing#layout-layout.js) or [`+layout.server.js`](routing#layout-layout.server.js). To define an option for the whole app, export it from the root layout. Child layouts and pages override values set in parent layouts, so — for example — you can enable prerendering for your entire app then disable it for pages that need to be dynamically rendered. You can mix and match these options in different areas of your app. For example, you could prerender your marketing page for maximum speed, server-render your dynamic pages for SEO and accessibility and turn your admin section into an SPA by rendering it on the client only. This makes SvelteKit very versatile. ## prerender It's likely that at least some routes of your app can be represented as a simple HTML file generated at build time. These routes can be [_prerendered_](glossary#Prerendering). ```js /// file: +page.js/+page.server.js/+server.js export const prerender = true; ``` Alternatively, you can set `export const prerender = true` in your root `+layout.js` or `+layout.server.js` and prerender everything except pages that are explicitly marked as _not_ prerenderable: ```js /// file: +page.js/+page.server.js/+server.js export const prerender = false; ``` Routes with `prerender = true` will be excluded from manifests used for dynamic SSR, making your server (or serverless/edge functions) smaller. In some cases you might want to prerender a route but also include it in the manifest (for example, with a route like `/blog/[slug]` where you want to prerender your most recent/popular content but server-render the long tail) — for these cases, there's a third option, 'auto': ```js /// file: +page.js/+page.server.js/+server.js export const prerender = 'auto'; ``` The prerenderer will start at the root of your app and generate files for any prerenderable pages or `+server.js` routes it finds. Each page is scanned for `<a>` elements that point to other pages that are candidates for prerendering — because of this, you generally don't need to specify which pages should be accessed. If you _do_ need to specify which pages should be accessed by the prerenderer, you can do so with [`config.kit.prerender.entries`](configuration#prerender), or by exporting an [`entries`](#entries) function from your dynamic route. While prerendering, the value of `building` imported from [`$app/environment`]($app-environment) will be `true`. ### Prerendering server routes Unlike the other page options, `prerender` also applies to `+server.js` files. These files are _not_ affected by layouts, but will inherit default values from the pages that fetch data from them, if any. For example if a `+page.js` contains this `load` function... ```js /// file: +page.js export const prerender = true; /** @type {import('./$types').PageLoad} */ export async function load({ fetch }) { const res = await fetch('/my-server-route.json'); return await res.json(); } ``` ...then `src/routes/my-server-route.json/+server.js` will be treated as prerenderable if it doesn't contain its own `export const prerender = false`. ### When not to prerender The basic rule is this: for a page to be prerenderable, any two users hitting it directly must get the same content from the server. Note that you can still prerender pages that load data based on the page's parameters, such as a `src/routes/blog/[slug]/+page.svelte` route. Accessing [`url.searchParams`](load#Using-URL-data-url) during prerendering is forbidden. If you need to use it, ensure you are only doing so in the browser (for example in `onMount`). Pages with [actions](form-actions) cannot be prerendered, because a server must be able to handle the action `POST` requests. ### Route conflicts Because prerendering writes to the filesystem, it isn't possible to have two endpoints that would cause a directory and a file to have the same name. For example, `src/routes/foo/+server.js` and `src/routes/foo/bar/+server.js` would try to create `foo` and `foo/bar`, which is impossible. For that reason among others, it's recommended that you always include a file extension — `src/routes/foo.json/+server.js` and `src/routes/foo/bar.json/+server.js` would result in `foo.json` and `foo/bar.json` files living harmoniously side-by-side. For _pages_, we skirt around this problem by writing `foo/index.html` instead of `foo`. ### Troubleshooting If you encounter an error like 'The following routes were marked as prerenderable, but were not prerendered' it's because the route in question (or a parent layout, if it's a page) has `export const prerender = true` but the page wasn't reached by the prerendering crawler and thus wasn't prerendered. Since these routes cannot be dynamically server-rendered, this will cause errors when people try to access the route in question. There are a few ways to fix it: * Ensure that SvelteKit can find the route by following links from [`config.kit.prerender.entries`](configuration#prerender) or the [`entries`](#entries) page option. Add links to dynamic routes (i.e. pages with `[parameters]` ) to this option if they are not found through crawling the other entry points, else they are not prerendered because SvelteKit doesn't know what value the parameters should have. Pages not marked as prerenderable will be ignored and their links to other pages will not be crawled, even if some of them would be prerenderable. * Ensure that SvelteKit can find the route by discovering a link to it from one of your other prerendered pages that have server-side rendering enabled. * Change `export const prerender = true` to `export const prerender = 'auto'`. Routes with `'auto'` can be dynamically server rendered ## entries SvelteKit will discover pages to prerender automatically, by starting at _entry points_ and crawling them. By default, all your non-dynamic routes are considered entry points — for example, if you have these routes... ```bash / # non-dynamic /blog # non-dynamic /blog/[slug] # dynamic, because of `[slug]` ``` ...SvelteKit will prerender `/` and `/blog`, and in the process discover links like `<a href="/blog/hello-world">` which give it new pages to prerender. Most of the time, that's enough. In some situations, links to pages like `/blog/hello-world` might not exist (or might not exist on prerendered pages), in which case we need to tell SvelteKit about their existence. This can be done with [`config.kit.prerender.entries`](configuration#prerender), or by exporting an `entries` function from a `+page.js`, a `+page.server.js` or a `+server.js` belonging to a dynamic route: ```js /// file: src/routes/blog/[slug]/+page.server.js /** @type {import('./$types').EntryGenerator} */ export function entries() { return [ { slug: 'hello-world' }, { slug: 'another-blog-post' } ]; } export const prerender = true; ``` `entries` can be an `async` function, allowing you to (for example) retrieve a list of posts from a CMS or database, in the example above. ## ssr Normally, SvelteKit renders your page on the server first and sends that HTML to the client where it's [hydrated](glossary#Hydration). If you set `ssr` to `false`, it renders an empty 'shell' page instead. This is useful if your page is unable to be rendered on the server (because you use browser-only globals like `document` for example), but in most situations it's not recommended ([see appendix](glossary#SSR)). ```js /// file: +page.js export const ssr = false; // If both `ssr` and `csr` are `false`, nothing will be rendered! ``` If you add `export const ssr = false` to your root `+layout.js`, your entire app will only be rendered on the client — which essentially means you turn your app into an SPA. ## csr Ordinarily, SvelteKit [hydrates](glossary#Hydration) your server-rendered HTML into an interactive client-side-rendered (CSR) page. Some pages don't require JavaScript at all — many blog posts and 'about' pages fall into this category. In these cases you can disable CSR: ```js /// file: +page.js export const csr = false; // If both `csr` and `ssr` are `false`, nothing will be rendered! ``` Disabling CSR does not ship any JavaScript to the client. This means: * The webpage should work with HTML and CSS only. * `<script>` tags inside all Svelte components are removed. * `<form>` elements cannot be [progressively enhanced](form-actions#Progressive-enhancement). * Links are handled by the browser with a full-page navigation. * Hot Module Replacement (HMR) will be disabled. You can enable `csr` during development (for example to take advantage of HMR) like so: ```js /// file: +page.js import { dev } from '$app/environment'; export const csr = dev; ``` ## trailingSlash By default, SvelteKit will remove trailing slashes from URLs — if you visit `/about/`, it will respond with a redirect to `/about`. You can change this behaviour with the `trailingSlash` option, which can be one of `'never'` (the default), `'always'`, or `'ignore'`. As with other page options, you can export this value from a `+layout.js` or a `+layout.server.js` and it will apply to all child pages. You can also export the configuration from `+server.js` files. ```js /// file: src/routes/+layout.js export const trailingSlash = 'always'; ``` This option also affects [prerendering](#prerender). If `trailingSlash` is `always`, a route like `/about` will result in an `about/index.html` file, otherwise it will create `about.html`, mirroring static webserver conventions. ## config With the concept of [adapters](adapters), SvelteKit is able to run on a variety of platforms. Each of these might have specific configuration to further tweak the deployment — for example on Vercel you could choose to deploy some parts of your app on the edge and others on serverless environments. `config` is an object with key-value pairs at the top level. Beyond that, the concrete shape is dependent on the adapter you're using. Every adapter should provide a `Config` interface to import for type safety. Consult the documentation of your adapter for more information. ```js // @filename: ambient.d.ts declare module 'some-adapter' { export interface Config { runtime: string } } // @filename: index.js // ---cut--- /// file: src/routes/+page.js /** @type {import('some-adapter').Config} */ export const config = { runtime: 'edge' }; ``` `config` objects are merged at the top level (but _not_ deeper levels). This means you don't need to repeat all the values in a `+page.js` if you want to only override some of the values in the upper `+layout.js`. For example this layout configuration... ```js /// file: src/routes/+layout.js export const config = { runtime: 'edge', regions: 'all', foo: { bar: true } } ``` ...is overridden by this page configuration... ```js /// file: src/routes/+page.js export const config = { regions: ['us1', 'us2'], foo: { baz: true } } ``` ...which results in the config value `{ runtime: 'edge', regions: ['us1', 'us2'], foo: { baz: true } }` for that page. ## Further reading - [Tutorial: Page options](/tutorial/kit/page-options)

# State management

If you're used to building client-only apps, state management in an app that spans server and client might seem intimidating. This section provides tips for avoiding some common gotchas. ## Avoid shared state on the server Browsers are _stateful_ — state is stored in memory as the user interacts with the application. Servers, on the other hand, are _stateless_ — the content of the response is determined entirely by the content of the request. Conceptually, that is. In reality, servers are often long-lived and shared by multiple users. For that reason it's important not to store data in shared variables. For example, consider this code: ```js // @errors: 7034 7005 /// file: +page.server.js let user; /** @type {import('./$types').PageServerLoad} */ export function load() { return { user }; } /** @satisfies {import('./$types').Actions} */ export const actions = { default: async ({ request }) => { const data = await request.formData(); // NEVER DO THIS! user = { name: data.get('name'), embarrassingSecret: data.get('secret') }; } } ``` The `user` variable is shared by everyone who connects to this server. If Alice submitted an embarrassing secret, and Bob visited the page after her, Bob would know Alice's secret. In addition, when Alice returns to the site later in the day, the server may have restarted, losing her data. Instead, you should _authenticate_ the user using [`cookies`](load#Cookies) and persist the data to a database. ## No side-effects in load For the same reason, your `load` functions should be _pure_ — no side-effects (except maybe the occasional `console.log(...)`). For example, you might be tempted to write to a store or global state inside a `load` function so that you can use the value in your components: ```js /// file: +page.js // @filename: ambient.d.ts declare module '$lib/user' { export const user: { set: (value: any) => void }; } // @filename: index.js // ---cut--- import { user } from '$lib/user'; /** @type {import('./$types').PageLoad} */ export async function load({ fetch }) { const response = await fetch('/api/user'); // NEVER DO THIS! user.set(await response.json()); } ``` As with the previous example, this puts one user's information in a place that is shared by _all_ users. Instead, just return the data... ```js /// file: +page.js /** @type {import('./$types').PageServerLoad} */ export async function load({ fetch }) { const response = await fetch('/api/user'); +++ return { user: await response.json() };+++ } ``` ...and pass it around to the components that need it, or use [`page.data`](load#page.data). If you're not using SSR, then there's no risk of accidentally exposing one user's data to another. But you should still avoid side-effects in your `load` functions — your application will be much easier to reason about without them. ## Using state and stores with context You might wonder how we're able to use `page.data` and other [app state]($app-state) (or [app stores]($app-stores)) if we can't use global state. The answer is that app state and app stores on the server use Svelte's [context API](/tutorial/svelte/context-api) — the state (or store) is attached to the component tree with `setContext`, and when you subscribe you retrieve it with `getContext`. We can do the same thing with our own state: ```svelte <!--- file: src/routes/+layout.svelte ---> <script> import { setContext } from 'svelte'; /** @type {import('./$types').LayoutProps} */ let { data } = $props(); // Pass a function referencing our state // to the context for child components to access setContext('user', () => data.user); </script> ``` ```svelte <!--- file: src/routes/user/+page.svelte ---> <script> import { getContext } from 'svelte'; // Retrieve user store from context const user = getContext('user'); </script> <p>Welcome {user().name}</p> ``` > You also use stores from `svelte/store` for this, but when using Svelte 5 it is recommended to make use of universal reactivity instead. Updating the value of context-based state in deeper-level pages or components while the page is being rendered via SSR will not affect the value in the parent component because it has already been rendered by the time the state value is updated. In contrast, on the client (when CSR is enabled, which is the default) the value will be propagated and components, pages, and layouts higher in the hierarchy will react to the new value. Therefore, to avoid values 'flashing' during state updates during hydration, it is generally recommended to pass state down into components rather than up. If you're not using SSR (and can guarantee that you won't need to use SSR in future) then you can safely keep state in a shared module, without using the context API. ## Component and page state is preserved When you navigate around your application, SvelteKit reuses existing layout and page components. For example, if you have a route like this... ```svelte <!--- file: src/routes/blog/[slug]/+page.svelte ---> <script> /** @type {import('./$types').PageProps} */ let { data } = $props(); // THIS CODE IS BUGGY! const wordCount = data.content.split(' ').length; const estimatedReadingTime = wordCount / 250; </script> <header> <h1>{data.title}</h1> <p>Reading time: {Math.round(estimatedReadingTime)} minutes</p> </header> <div>{@html data.content}</div> ``` ...then navigating from `/blog/my-short-post` to `/blog/my-long-post` won't cause the layout, page and any other components within to be destroyed and recreated. Instead the `data` prop (and by extension `data.title` and `data.content`) will update (as it would with any other Svelte component) and, because the code isn't rerunning, lifecycle methods like `onMount` and `onDestroy` won't rerun and `estimatedReadingTime` won't be recalculated. Instead, we need to make the value [_reactive_](/tutorial/svelte/state): ```svelte /// file: src/routes/blog/[slug]/+page.svelte <script> /** @type {import('./$types').PageProps} */ let { data } = $props(); +++ let wordCount = $derived(data.content.split(' ').length); let estimatedReadingTime = $derived(wordCount / 250);+++ </script> ``` Reusing components like this means that things like sidebar scroll state are preserved, and you can easily animate between changing values. In the case that you do need to completely destroy and remount a component on navigation, you can use this pattern: ```svelte <script> import { page } from '$app/state'; </script> {#key page.url.pathname} <BlogPost title={data.title} content={data.title} /> {/key} ``` ## Storing state in the URL If you have state that should survive a reload and/or affect SSR, such as filters or sorting rules on a table, URL search parameters (like `?sort=price&order=ascending`) are a good place to put them. You can put them in `<a href="...">` or `<form action="...">` attributes, or set them programmatically via `goto('?key=value')`. They can be accessed inside `load` functions via the `url` parameter, and inside components via `page.url.searchParams`. ## Storing ephemeral state in snapshots Some UI state, such as 'is the accordion open?', is disposable — if the user navigates away or refreshes the page, it doesn't matter if the state is lost. In some cases, you _do_ want the data to persist if the user navigates to a different page and comes back, but storing the state in the URL or in a database would be overkill. For this, SvelteKit provides [snapshots](snapshots), which let you associate component state with a history entry.

# Building your app

Building a SvelteKit app happens in two stages, which both happen when you run `vite build` (usually via `npm run build`). Firstly, Vite creates an optimized production build of your server code, your browser code, and your service worker (if you have one). [Prerendering](page-options#prerender) is executed at this stage, if appropriate. Secondly, an _adapter_ takes this production build and tunes it for your target environment — more on this on the following pages. ## During the build SvelteKit will load your `+page/layout(.server).js` files (and all files they import) for analysis during the build. Any code that should _not_ be executed at this stage must check that `building` from [`$app/environment`]($app-environment) is `false`: ```js +++import { building } from '$app/environment';+++ import { setupMyDatabase } from '$lib/server/database'; +++if (!building) {+++ setupMyDatabase(); +++}+++ export function load() { // ... } ``` ## Preview your app After building, you can view your production build locally with `vite preview` (via `npm run preview`). Note that this will run the app in Node, and so is not a perfect reproduction of your deployed app — adapter-specific adjustments like the [`platform` object](adapters#Platform-specific-context) do not apply to previews.

# Adapters

Before you can deploy your SvelteKit app, you need to _adapt_ it for your deployment target. Adapters are small plugins that take the built app as input and generate output for deployment. Official adapters exist for a variety of platforms — these are documented on the following pages: - [`@sveltejs/adapter-cloudflare`](adapter-cloudflare) for Cloudflare Pages - [`@sveltejs/adapter-cloudflare-workers`](adapter-cloudflare-workers) for Cloudflare Workers - [`@sveltejs/adapter-netlify`](adapter-netlify) for Netlify - [`@sveltejs/adapter-node`](adapter-node) for Node servers - [`@sveltejs/adapter-static`](adapter-static) for static site generation (SSG) - [`@sveltejs/adapter-vercel`](adapter-vercel) for Vercel Additional [community-provided adapters](https://sveltesociety.dev/packages?category=sveltekit-adapters) exist for other platforms. ## Using adapters Your adapter is specified in `svelte.config.js`: ```js /// file: svelte.config.js // @filename: ambient.d.ts declare module 'svelte-adapter-foo' { const adapter: (opts: any) => import('@sveltejs/kit').Adapter; export default adapter; } // @filename: index.js // ---cut--- 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 Some adapters may have access to additional information about the request. For example, Cloudflare Workers can access an `env` object containing KV namespaces etc. This can be passed to the `RequestEvent` used in [hooks](hooks) and [server routes](routing#server) as the `platform` property — consult each adapter's documentation to learn more.

# Single-page apps

You can turn any SvelteKit app, using any adapter, into a fully client-rendered single-page app (SPA) by disabling SSR at the root layout: ```js /// file: src/routes/+layout.js export const ssr = false; ``` If you don't have any server-side logic (i.e. `+page.server.js`, `+layout.server.js` or `+server.js` files) you can use [`adapter-static`](adapter-static) to create your SPA by adding a _fallback page_. ## Usage Install with `npm i -D @sveltejs/adapter-static`, then add the adapter to your `svelte.config.js` with the following options: ```js // @errors: 2307 /// file: svelte.config.js import adapter from '@sveltejs/adapter-static'; export default { kit: { adapter: adapter({ fallback: '200.html' // may differ from host to host }) } }; ``` The `fallback` page is an HTML page created by SvelteKit from your page template (e.g. `app.html`) that loads your app and navigates to the correct route. For example [Surge](https://surge.sh/help/adding-a-200-page-for-client-side-routing), a static web host, lets you add a `200.html` file that will handle any requests that don't correspond to static assets or prerendered pages. On some hosts it may be `index.html` or something else entirely — consult your platform's documentation. ## Apache To run an SPA on [Apache](https://httpd.apache.org/), you should add a `static/.htaccess` file to route requests to the fallback page: ``` <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^200\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /200.html [L] </IfModule> ``` ## Prerendering individual pages If you want certain pages to be prerendered, you can re-enable `ssr` alongside `prerender` for just those parts of your app: ```js /// file: src/routes/my-prerendered-page/+page.js export const prerender = true; export const ssr = true; ```

# Advanced routing

## Rest parameters If the number of route segments is unknown, you can use rest syntax — for example you might implement GitHub's file viewer like so... ```bash /[org]/[repo]/tree/[branch]/[...file] ``` ...in which case a request for `/sveltejs/kit/tree/main/documentation/docs/04-advanced-routing.md` would result in the following parameters being available to the page: ```js // @noErrors { org: 'sveltejs', repo: 'kit', branch: 'main', file: 'documentation/docs/04-advanced-routing.md' } ``` ### 404 pages Rest parameters also allow you to render custom 404s. Given these routes... ```tree src/routes/ ├ marx-brothers/ │ ├ chico/ │ ├ harpo/ │ ├ groucho/ │ └ +error.svelte └ +error.svelte ``` ...the `marx-brothers/+error.svelte` file will _not_ be rendered if you visit `/marx-brothers/karl`, because no route was matched. If you want to render the nested error page, you should create a route that matches any `/marx-brothers/*` request, and return a 404 from it: ```tree src/routes/ ├ marx-brothers/ +++| ├ [...path]/+++ │ ├ chico/ │ ├ harpo/ │ ├ groucho/ │ └ +error.svelte └ +error.svelte ``` ```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 A route like `[lang]/home` contains a parameter named `lang` which is required. Sometimes it's beneficial to make these parameters optional, so that in this example both `home` and `en/home` point to the same page. You can do that by wrapping the parameter in another bracket pair: `[[lang]]/home` Note that an optional route parameter cannot follow a rest parameter (`[...rest]/[[optional]]`), since parameters are matched 'greedily' and the optional parameter would always be unused. ## Matching A route like `src/routes/fruits/[page]` would match `/fruits/apple`, but it would also match `/fruits/rocketship`. We don't want that. You can ensure that route parameters are well-formed by adding a _matcher_ — which takes the parameter string (`"apple"` or `"rocketship"`) and returns `true` if it is valid — to your [`params`](configuration#files) directory... ```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'; } ``` ...and augmenting your routes: ``` src/routes/fruits/[page+++=fruit+++] ``` If the pathname doesn't match, SvelteKit will try to match other routes (using the sort order specified below), before eventually returning a 404. Each module in the `params` directory corresponds to a matcher, with the exception of `*.test.js` and `*.spec.js` files which may be used to unit test your matchers. ## Sorting It's possible for multiple routes to match a given path. For example each of these routes would match `/foo-abc`: ```bash src/routes/[...catchall]/+page.svelte src/routes/[[a=x]]/+page.svelte src/routes/[b]/+page.svelte src/routes/foo-[c]/+page.svelte src/routes/foo-abc/+page.svelte ``` SvelteKit needs to know which route is being requested. To do so, it sorts them according to the following rules... - More specific routes are higher priority (e.g. a route with no parameters is more specific than a route with one dynamic parameter, and so on) - Parameters with [matchers](#Matching) (`[name=type]`) are higher priority than those without (`[name]`) - `[[optional]]` and `[...rest]` parameters are ignored unless they are the final part of the route, in which case they are treated with lowest priority. In other words `x/[[y]]/z` is treated equivalently to `x/z` for the purposes of sorting - Ties are resolved alphabetically ...resulting in this ordering, meaning that `/foo-abc` will invoke `src/routes/foo-abc/+page.svelte`, and `/foo-def` will invoke `src/routes/foo-[c]/+page.svelte` rather than less specific routes: ```bash src/routes/foo-abc/+page.svelte src/routes/foo-[c]/+page.svelte src/routes/[[a=x]]/+page.svelte src/routes/[b]/+page.svelte src/routes/[...catchall]/+page.svelte ``` ## Encoding Some characters can't be used on the filesystem — `/` on Linux and Mac, `\ / : * ? " < > |` on Windows. The `#` and `%` characters have special meaning in URLs, and the `[ ] ( )` characters have special meaning to SvelteKit, so these also can't be used directly as part of your route. To use these characters in your routes, you can use hexadecimal escape sequences, which have the format `[x+nn]` where `nn` is a hexadecimal character code: - `\` — `[x+5c]` - `/` — `[x+2f]` - `:` — `[x+3a]` - `*` — `[x+2a]` - `?` — `[x+3f]` - `"` — `[x+22]` - `<` — `[x+3c]` - `>` — `[x+3e]` - `|` — `[x+7c]` - `#` — `[x+23]` - `%` — `[x+25]` - `[` — `[x+5b]` - `]` — `[x+5d]` - `(` — `[x+28]` - `)` — `[x+29]` For example, to create a `/smileys/:-)` route, you would create a `src/routes/smileys/[x+3a]-[x+29]/+page.svelte` file. You can determine the hexadecimal code for a character with JavaScript: ```js ':'.charCodeAt(0).toString(16); // '3a', hence '[x+3a]' ``` You can also use Unicode escape sequences. Generally you won't need to as you can use the unencoded character directly, but if — for some reason — you can't have a filename with an emoji in it, for example, then you can use the escaped characters. In other words, these are equivalent: ``` src/routes/[u+d83e][u+dd2a]/+page.svelte src/routes/🤪/+page.svelte ``` The format for a Unicode escape sequence is `[u+nnnn]` where `nnnn` is a valid value between `0000` and `10ffff`. (Unlike JavaScript string escaping, there's no need to use surrogate pairs to represent code points above `ffff`.) To learn more about Unicode encodings, consult [Programming with Unicode](https://unicodebook.readthedocs.io/unicode_encodings.html). ## Advanced layouts By default, the _layout hierarchy_ mirrors the _route hierarchy_. In some cases, that might not be what you want. ### (group) Perhaps you have some routes that are 'app' routes that should have one layout (e.g. `/dashboard` or `/item`), and others that are 'marketing' routes that should have a different layout (`/about` or `/testimonials`). We can group these routes with a directory whose name is wrapped in parentheses — unlike normal directories, `(app)` and `(marketing)` do not affect the URL pathname of the routes inside them: ```tree src/routes/ +++│ (app)/+++ │ ├ dashboard/ │ ├ item/ │ └ +layout.svelte +++│ (marketing)/+++ │ ├ about/ │ ├ testimonials/ │ └ +layout.svelte ├ admin/ └ +layout.svelte ``` You can also put a `+page` directly inside a `(group)`, for example if `/` should be an `(app)` or a `(marketing)` page. ### Breaking out of layouts The root layout applies to every page of your app — if omitted, it defaults to `{@render children()}`. If you want some pages to have a different layout hierarchy than the rest, then you can put your entire app inside one or more groups _except_ the routes that should not inherit the common layouts. In the example above, the `/admin` route does not inherit either the `(app)` or `(marketing)` layouts. ### +page@ Pages can break out of the current layout hierarchy on a route-by-route basis. Suppose we have an `/item/[id]/embed` route inside the `(app)` group from the previous example: ```tree src/routes/ ├ (app)/ │ ├ item/ │ │ ├ [id]/ │ │ │ ├ embed/ +++│ │ │ │ └ +page.svelte+++ │ │ │ └ +layout.svelte │ │ └ +layout.svelte │ └ +layout.svelte └ +layout.svelte ``` Ordinarily, this would inherit the root layout, the `(app)` layout, the `item` layout and the `[id]` layout. We can reset to one of those layouts by appending `@` followed by the segment name — or, for the root layout, the empty string. In this example, we can choose from the following options: - `+page@[id].svelte` - inherits from `src/routes/(app)/item/[id]/+layout.svelte` - `+page@item.svelte` - inherits from `src/routes/(app)/item/+layout.svelte` - `+page@(app).svelte` - inherits from `src/routes/(app)/+layout.svelte` - `+page@.svelte` - inherits from `src/routes/+layout.svelte` ```tree src/routes/ ├ (app)/ │ ├ item/ │ │ ├ [id]/ │ │ │ ├ embed/ +++│ │ │ │ └ +page@(app).svelte+++ │ │ │ └ +layout.svelte │ │ └ +layout.svelte │ └ +layout.svelte └ +layout.svelte ``` ### +layout@ Like pages, layouts can _themselves_ break out of their parent layout hierarchy, using the same technique. For example, a `+layout@.svelte` component would reset the hierarchy for all its child routes. ``` src/routes/ ├ (app)/ │ ├ item/ │ │ ├ [id]/ │ │ │ ├ embed/ │ │ │ │ └ +page.svelte // uses (app)/item/[id]/+layout.svelte │ │ │ ├ +layout.svelte // inherits from (app)/item/+layout@.svelte │ │ │ └ +page.svelte // uses (app)/item/+layout@.svelte │ │ └ +layout@.svelte // inherits from root layout, skipping (app)/+layout.svelte │ └ +layout.svelte └ +layout.svelte ``` ### When to use layout groups Not all use cases are suited for layout grouping, nor should you feel compelled to use them. It might be that your use case would result in complex `(group)` nesting, or that you don't want to introduce a `(group)` for a single outlier. It's perfectly fine to use other means such as composition (reusable `load` functions or Svelte components) or if-statements to achieve what you want. The following example shows a layout that rewinds to the root layout and reuses components and functions that other layouts can also use: ```svelte <!--- file: src/routes/nested/route/+layout@.svelte ---> <script> import ReusableLayout from '$lib/ReusableLayout.svelte'; let { data, children } = $props(); </script> <ReusableLayout {data}> {@render children()} </ReusableLayout> ``` ```js /// file: src/routes/nested/route/+layout.js // @filename: ambient.d.ts declare module "$lib/reusable-load-function" { export function reusableLoad(event: import('@sveltejs/kit').LoadEvent): Promise<Record<string, any>>; } // @filename: index.js // ---cut--- import { reusableLoad } from '$lib/reusable-load-function'; /** @type {import('./$types').PageLoad} */ export function load(event) { // Add additional logic here, if needed return reusableLoad(event); } ``` ## Further reading - [Tutorial: Advanced Routing](/tutorial/kit/optional-params)

# Hooks

'Hooks' are app-wide functions you declare that SvelteKit will call in response to specific events, giving you fine-grained control over the framework's behaviour. There are three hooks files, all optional: - `src/hooks.server.js` — your app's server hooks - `src/hooks.client.js` — your app's client hooks - `src/hooks.js` — your app's hooks that run on both the client and server Code in these modules will run when the application starts up, making them useful for initializing database clients and so on. ## Server hooks The following hooks can be added to `src/hooks.server.js`: ### handle This function runs every time the SvelteKit server receives a [request](web-standards#Fetch-APIs-Request) — whether that happens while the app is running, or during [prerendering](page-options#prerender) — and determines the [response](web-standards#Fetch-APIs-Response). It receives an `event` object representing the request and a function called `resolve`, which renders the route and generates a `Response`. This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example). ```js /// file: src/hooks.server.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; } ``` If unimplemented, defaults to `({ event, resolve }) => resolve(event)`. During prerendering, SvelteKit crawls your pages for links and renders each route it finds. Rendering the route invokes the `handle` function (and all other route dependencies, like `load`). If you need to exclude some code from running during this phase, check that the app is not [`building`]($app-environment#building) beforehand. ### locals To add custom data to the request, which is passed to handlers in `+server.js` and server `load` functions, populate the `event.locals` object, as shown below. ```js /// file: src/hooks.server.js // @filename: ambient.d.ts type User = { name: string; } declare namespace App { interface Locals { user: User; } } const getUserInformation: (cookie: string | void) => Promise<User>; // @filename: index.js // ---cut--- /** @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); // Note that modifying response headers isn't always safe. // Response objects can have immutable headers // (e.g. Response.redirect() returned from an endpoint). // Modifying immutable headers throws a TypeError. // In that case, clone the response or avoid creating a // response object with immutable headers. response.headers.set('x-custom-header', 'potato'); return response; } ``` You can define multiple `handle` functions and execute them with [the `sequence` helper function](@sveltejs-kit-hooks). `resolve` also supports a second, optional parameter that gives you more control over how the response will be rendered. That parameter is an object that can have the following fields: - `transformPageChunk(opts: { html: string, done: boolean }): MaybePromise<string | undefined>` — applies custom transforms to HTML. If `done` is true, it's the final chunk. Chunks are not guaranteed to be well-formed HTML (they could include an element's opening tag but not its closing tag, for example) but they will always be split at sensible boundaries such as `%sveltekit.head%` or layout/page components. - `filterSerializedResponseHeaders(name: string, value: string): boolean` — determines which headers should be included in serialized responses when a `load` function loads a resource with `fetch`. By default, none will be included. - `preload(input: { type: 'js' | 'css' | 'font' | 'asset', path: string }): boolean` — determines what files should be added to the `<head>` tag to preload it. The method is called with each file that was found at build time while constructing the code chunks — so if you for example have `import './styles.css` in your `+page.svelte`, `preload` will be called with the resolved path to that CSS file when visiting that page. Note that in dev mode `preload` is _not_ called, since it depends on analysis that happens at build time. Preloading can improve performance by downloading assets sooner, but it can also hurt if too much is downloaded unnecessarily. By default, `js` and `css` files will be preloaded. `asset` files are not preloaded at all currently, but we may add this later after evaluating feedback. ```js /// file: src/hooks.server.js /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { const response = await resolve(event, { transformPageChunk: ({ html }) => html.replace('old', 'new'), filterSerializedResponseHeaders: (name) => name.startsWith('x-'), preload: ({ type, path }) => type === 'js' || path.includes('/important/') }); return response; } ``` Note that `resolve(...)` will never throw an error, it will always return a `Promise<Response>` with the appropriate status code. If an error is thrown elsewhere during `handle`, it is treated as fatal, and SvelteKit will respond with a JSON representation of the error or a fallback error page — which can be customised via `src/error.html` — depending on the `Accept` header. You can read more about error handling [here](errors). ### handleFetch This function allows you to modify (or replace) a `fetch` request that happens inside a `load` or `action` function that runs on the server (or during pre-rendering). For example, your `load` function might make a request to a public URL like `https://api.yourapp.com` when the user performs a client-side navigation to the respective page, but during SSR it might make sense to hit the API directly (bypassing whatever proxies and load balancers sit between it and the public internet). ```js /// file: src/hooks.server.js /** @type {import('@sveltejs/kit').HandleFetch} */ export async function handleFetch({ request, fetch }) { if (request.url.startsWith('https://api.yourapp.com/')) { // clone the original request, but change the URL request = new Request( request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'), request ); } return fetch(request); } ``` **Credentials** For same-origin requests, SvelteKit's `fetch` implementation will forward `cookie` and `authorization` headers unless the `credentials` option is set to `"omit"`. For cross-origin requests, `cookie` will be included if the request URL belongs to a subdomain of the app — for example if your app is on `my-domain.com`, and your API is on `api.my-domain.com`, cookies will be included in the request. If your app and your API are on sibling subdomains — `www.my-domain.com` and `api.my-domain.com` for example — then a cookie belonging to a common parent domain like `my-domain.com` will _not_ be included, because SvelteKit has no way to know which domain the cookie belongs to. In these cases you will need to manually include the cookie using `handleFetch`: ```js /// file: src/hooks.server.js // @errors: 2345 /** @type {import('@sveltejs/kit').HandleFetch} */ export async function handleFetch({ event, request, fetch }) { if (request.url.startsWith('https://api.my-domain.com/')) { request.headers.set('cookie', event.request.headers.get('cookie')); } return fetch(request); } ``` ## Shared hooks The following can be added to `src/hooks.server.js` _and_ `src/hooks.client.js`: ### handleError If an [unexpected error](errors#Unexpected-errors) is thrown during loading or rendering, this function will be called with the `error`, `event`, `status` code and `message`. This allows for two things: - you can log the error - you can generate a custom representation of the error that is safe to show to users, omitting sensitive details like messages and stack traces. The returned value, which defaults to `{ message }`, becomes the value of `$page.error`. For errors thrown from your code (or library code called by your code) the status will be 500 and the message will be "Internal Error". While `error.message` may contain sensitive information that should not be exposed to users, `message` is safe (albeit meaningless to the average user). To add more information to the `$page.error` object in a type-safe way, you can customize the expected shape by declaring an `App.Error` interface (which must include `message: string`, to guarantee sensible fallback behavior). This allows you to — for example — append a tracking ID for users to quote in correspondence with your technical support staff: ```ts /// file: src/app.d.ts declare global { namespace App { interface Error { message: string; errorId: string; } } } export {}; ``` ```js /// file: src/hooks.server.js // @errors: 2322 2353 // @filename: ambient.d.ts declare module '@sentry/sveltekit' { export const init: (opts: any) => void; export const captureException: (error: any, opts: any) => void; } // @filename: index.js // ---cut--- import * as Sentry from '@sentry/sveltekit'; Sentry.init({/*...*/}) /** @type {import('@sveltejs/kit').HandleServerError} */ export async function handleError({ error, event, status, message }) { const errorId = crypto.randomUUID(); // example integration with https://sentry.io/ Sentry.captureException(error, { extra: { event, errorId, status } }); return { message: 'Whoops!', errorId }; } ``` ```js /// file: src/hooks.client.js // @errors: 2322 2353 // @filename: ambient.d.ts declare module '@sentry/sveltekit' { export const init: (opts: any) => void; export const captureException: (error: any, opts: any) => void; } // @filename: index.js // ---cut--- import * as Sentry from '@sentry/sveltekit'; Sentry.init({/*...*/}) /** @type {import('@sveltejs/kit').HandleClientError} */ export async function handleError({ error, event, status, message }) { const errorId = crypto.randomUUID(); // example integration with https://sentry.io/ Sentry.captureException(error, { extra: { event, errorId, status } }); return { message: 'Whoops!', errorId }; } ``` This function is not called for _expected_ errors (those thrown with the [`error`](@sveltejs-kit#error) function imported from `@sveltejs/kit`). During development, if an error occurs because of a syntax error in your Svelte code, the passed in error has a `frame` property appended highlighting the location of the error. ### init This function runs once, when the server is created or the app starts in the browser, and is a useful place to do asynchronous work such as initializing a database connection. ```js /// file: src/hooks.server.js import * as db from '$lib/server/database'; /** @type {import('@sveltejs/kit').ServerInit} */ export async function init() { await db.connect(); } ``` > In the browser, asynchronous work in `init` will delay hydration, so be mindful of what you put in there. ## Universal hooks The following can be added to `src/hooks.js`. Universal hooks run on both server and client (not to be confused with shared hooks, which are environment-specific). ### reroute This function runs before `handle` and allows you to change how URLs are translated into routes. The returned pathname (which defaults to `url.pathname`) is used to select the route and its parameters. For example, you might have a `src/routes/[[lang]]/about/+page.svelte` page, which should be accessible as `/en/about` or `/de/ueber-uns` or `/fr/a-propos`. You could implement this with `reroute`: ```js /// file: src/hooks.js // @errors: 2345 // @errors: 2304 /** @type {Record<string, string>} */ 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]; } } ``` The `lang` parameter will be correctly derived from the returned pathname. Using `reroute` will _not_ change the contents of the browser's address bar, or the value of `event.url`. Since version 2.18, the `reroute` hook can be asynchronous, allowing it to (for example) fetch data from your backend to decide where to reroute to. Use this carefully and make sure it's fast, as it will delay navigation otherwise. ### transport This is a collection of _transporters_, which allow you to pass custom types — returned from `load` and form actions — across the server/client boundary. Each transporter contains an `encode` function, which encodes values on the server (or returns `false` for anything that isn't an instance of the type) and a corresponding `decode` function: ```js /// file: src/hooks.js import { Vector } from '$lib/math'; /** @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) } }; ``` ## Further reading - [Tutorial: Hooks](/tutorial/kit/handle)

# Errors

Errors are an inevitable fact of software development. SvelteKit handles errors differently depending on where they occur, what kind of errors they are, and the nature of the incoming request. ## Error objects SvelteKit distinguishes between expected and unexpected errors, both of which are represented as simple `{ message: string }` objects by default. You can add additional properties, like a `code` or a tracking `id`, as shown in the examples below. (When using TypeScript this requires you to redefine the `Error` type as described in [type safety](errors#Type-safety)). ## Expected errors An _expected_ error is one created with the [`error`](@sveltejs-kit#error) helper imported from `@sveltejs/kit`: ```js /// file: src/routes/blog/[slug]/+page.server.js // @filename: ambient.d.ts declare module '$lib/server/database' { export function getPost(slug: string): Promise<{ title: string, content: string } | undefined> } // @filename: index.js // ---cut--- import { error } from '@sveltejs/kit'; import * as db from '$lib/server/database'; /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { const post = await db.getPost(params.slug); if (!post) { error(404, { message: 'Not found' }); } return { post }; } ``` This throws an exception that SvelteKit catches, causing it to set the response status code to 404 and render an [`+error.svelte`](routing#error) component, where `page.error` is the object provided as the second argument to `error(...)`. ```svelte <!--- file: src/routes/+error.svelte ---> <script> import { page } from '$app/state'; </script> <h1>{page.error.message}</h1> ``` > `$app/state` was added in SvelteKit 2.12. If you're using an earlier version or are using Svelte 4, use `$app/stores` instead. You can add extra properties to the error object if needed... ```js // @filename: ambient.d.ts declare global { namespace App { interface Error { message: string; code: string; } } } export {} // @filename: index.js import { error } from '@sveltejs/kit'; // ---cut--- error(404, { message: 'Not found', +++code: 'NOT_FOUND'+++ }); ``` ...otherwise, for convenience, you can pass a string as the second argument: ```js import { error } from '@sveltejs/kit'; // ---cut--- ---error(404, { message: 'Not found' });--- +++error(404, 'Not found');+++ ``` ## Unexpected errors An _unexpected_ error is any other exception that occurs while handling a request. Since these can contain sensitive information, unexpected error messages and stack traces are not exposed to users. By default, unexpected errors are printed to the console (or, in production, your server logs), while the error that is exposed to the user has a generic shape: ```json { "message": "Internal Error" } ``` Unexpected errors will go through the [`handleError`](hooks#Shared-hooks-handleError) hook, where you can add your own error handling — for example, sending errors to a reporting service, or returning a custom error object which becomes `$page.error`. ## Responses If an error occurs inside `handle` or inside a [`+server.js`](routing#server) request handler, SvelteKit will respond with either a fallback error page or a JSON representation of the error object, depending on the request's `Accept` headers. You can customise the fallback error page by adding a `src/error.html` file: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>%sveltekit.error.message%</title> </head> <body> <h1>My custom error page</h1> <p>Status: %sveltekit.status%</p> <p>Message: %sveltekit.error.message%</p> </body> </html> ``` SvelteKit will replace `%sveltekit.status%` and `%sveltekit.error.message%` with their corresponding values. If the error instead occurs inside a `load` function while rendering a page, SvelteKit will render the [`+error.svelte`](routing#error) component nearest to where the error occurred. If the error occurs inside a `load` function in `+layout(.server).js`, the closest error boundary in the tree is an `+error.svelte` file _above_ that layout (not next to it). The exception is when the error occurs inside the root `+layout.js` or `+layout.server.js`, since the root layout would ordinarily _contain_ the `+error.svelte` component. In this case, SvelteKit uses the fallback error page. ## Type safety If you're using TypeScript and need to customize the shape of errors, you can do so by declaring an `App.Error` interface in your app (by convention, in `src/app.d.ts`, though it can live anywhere that TypeScript can 'see'): ```ts /// file: src/app.d.ts declare global { namespace App { interface Error { +++ code: string; id: string;+++ } } } export {}; ``` This interface always includes a `message: string` property. ## Further reading - [Tutorial: Errors and redirects](/tutorial/kit/error-basics) - [Tutorial: Hooks](/tutorial/kit/handle)

# Link options

In SvelteKit, `<a>` elements (rather than framework-specific `<Link>` components) are used to navigate between the routes of your app. If the user clicks on a link whose `href` is 'owned' by the app (as opposed to, say, a link to an external site) then SvelteKit will navigate to the new page by importing its code and then calling any `load` functions it needs to fetch data. You can customise the behaviour of links with `data-sveltekit-*` attributes. These can be applied to the `<a>` itself, or to a parent element. These options also apply to `<form>` elements with [`method="GET"`](form-actions#GET-vs-POST). ## data-sveltekit-preload-data Before the browser registers that the user has clicked on a link, we can detect that they've hovered the mouse over it (on desktop) or that a `touchstart` or `mousedown` event was triggered. In both cases, we can make an educated guess that a `click` event is coming. SvelteKit can use this information to get a head start on importing the code and fetching the page's data, which can give us an extra couple of hundred milliseconds — the difference between a user interface that feels laggy and one that feels snappy. We can control this behaviour with the `data-sveltekit-preload-data` attribute, which can have one of two values: - `"hover"` means that preloading will start if the mouse comes to a rest over a link. On mobile, preloading begins on `touchstart` - `"tap"` means that preloading will start as soon as a `touchstart` or `mousedown` event is registered The default project template has a `data-sveltekit-preload-data="hover"` attribute applied to the `<body>` element in `src/app.html`, meaning that every link is preloaded on hover by default: ```html <body data-sveltekit-preload-data="hover"> <div style="display: contents">%sveltekit.body%</div> </body> ``` Sometimes, calling `load` when the user hovers over a link might be undesirable, either because it's likely to result in false positives (a click needn't follow a hover) or because data is updating very quickly and a delay could mean staleness. In these cases, you can specify the `"tap"` value, which causes SvelteKit to call `load` only when the user taps or clicks on a link: ```html <a data-sveltekit-preload-data="tap" href="/stonks"> Get current stonk values </a> ``` Data will never be preloaded if the user has chosen reduced data usage, meaning [`navigator.connection.saveData`](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/saveData) is `true`. ## data-sveltekit-preload-code Even in cases where you don't want to preload _data_ for a link, it can be beneficial to preload the _code_. The `data-sveltekit-preload-code` attribute works similarly to `data-sveltekit-preload-data`, except that it can take one of four values, in decreasing 'eagerness': - `"eager"` means that links will be preloaded straight away - `"viewport"` means that links will be preloaded once they enter the viewport - `"hover"` - as above, except that only code is preloaded - `"tap"` - as above, except that only code is preloaded Note that `viewport` and `eager` only apply to links that are present in the DOM immediately following navigation — if a link is added later (in an `{#if ...}` block, for example) it will not be preloaded until triggered by `hover` or `tap`. This is to avoid performance pitfalls resulting from aggressively observing the DOM for changes. As with `data-sveltekit-preload-data`, this attribute will be ignored if the user has chosen reduced data usage. ## data-sveltekit-reload Occasionally, we need to tell SvelteKit not to handle a link, but allow the browser to handle it. Adding a `data-sveltekit-reload` attribute to a link... ```html <a data-sveltekit-reload href="/path">Path</a> ``` ...will cause a full-page navigation when the link is clicked. Links with a `rel="external"` attribute will receive the same treatment. In addition, they will be ignored during [prerendering](page-options#prerender). ## data-sveltekit-replacestate Sometimes you don't want navigation to create a new entry in the browser's session history. Adding a `data-sveltekit-replacestate` attribute to a link... ```html <a data-sveltekit-replacestate href="/path">Path</a> ``` ...will replace the current `history` entry rather than creating a new one with `pushState` when the link is clicked. ## data-sveltekit-keepfocus Sometimes you don't want [focus to be reset](accessibility#Focus-management) after navigation. For example, maybe you have a search form that submits as the user is typing, and you want to keep focus on the text input. Adding a `data-sveltekit-keepfocus` attribute to it... ```html <form data-sveltekit-keepfocus> <input type="text" name="query"> </form> ``` ...will cause the currently focused element to retain focus after navigation. In general, avoid using this attribute on links, since the focused element would be the `<a>` tag (and not a previously focused element) and screen reader and other assistive technology users often expect focus to be moved after a navigation. You should also only use this attribute on elements that still exist after navigation. If the element no longer exists, the user's focus will be lost, making for a confusing experience for assistive technology users. ## data-sveltekit-noscroll When navigating to internal links, SvelteKit mirrors the browser's default navigation behaviour: it will change the scroll position to 0,0 so that the user is at the very top left of the page (unless the link includes a `#hash`, in which case it will scroll to the element with a matching ID). In certain cases, you may wish to disable this behaviour. Adding a `data-sveltekit-noscroll` attribute to a link... ```html <a href="path" data-sveltekit-noscroll>Path</a> ``` ...will prevent scrolling after the link is clicked. ## Disabling options To disable any of these options inside an element where they have been enabled, use the `"false"` value: ```html <div data-sveltekit-preload-data> <!-- these links will be preloaded --> <a href="/a">a</a> <a href="/b">b</a> <a href="/c">c</a> <div data-sveltekit-preload-data="false"> <!-- these links will NOT be preloaded --> <a href="/d">d</a> <a href="/e">e</a> <a href="/f">f</a> </div> </div> ``` To apply an attribute to an element conditionally, do this: ```svelte <div data-sveltekit-preload-data={condition ? 'hover' : false}> ```

# Service workers

Service workers act as proxy servers that handle network requests inside your app. This makes it possible to make your app work offline, but even if you don't need offline support (or can't realistically implement it because of the type of app you're building), it's often worth using service workers to speed up navigation by precaching your built JS and CSS. In SvelteKit, if you have a `src/service-worker.js` file (or `src/service-worker/index.js`) it will be bundled and automatically registered. You can change the [location of your service worker](configuration#files) if you need to. You can [disable automatic registration](configuration#serviceWorker) if you need to register the service worker with your own logic or use another solution. The default registration looks something like this: ```js if ('serviceWorker' in navigator) { addEventListener('load', function () { navigator.serviceWorker.register('./path/to/service-worker.js'); }); } ``` ## Inside the service worker Inside the service worker you have access to the [`$service-worker` module]($service-worker), which provides you with the paths to all static assets, build files and prerendered pages. You're also provided with an app version string, which you can use for creating a unique cache name, and the deployment's `base` path. If your Vite config specifies `define` (used for global variable replacements), this will be applied to service workers as well as your server/client builds. The following example caches the built app and any files in `static` eagerly, and caches all other requests as they happen. This would make each page work offline once visited. ```js // @errors: 2339 /// <reference types="@sveltejs/kit" /> 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 // as there is nothing we can do to respond to this request throw err; } } event.respondWith(respond()); }); ``` ## During development The service worker is bundled for production, but not during development. For that reason, only browsers that support [modules in service workers](https://web.dev/es-modules-in-sw) will be able to use them at dev time. If you are manually registering your service worker, you will need to pass the `{ type: 'module' }` option in development: ```js import { dev } from '$app/environment'; navigator.serviceWorker.register('/service-worker.js', { type: dev ? 'module' : 'classic' }); ``` ## Type safety Setting up proper types for service workers requires some manual setup. Inside your `service-worker.js`, add the following to the top of your file: ```original-js /// <reference types="@sveltejs/kit" /> /// <reference no-default-lib="true"/> /// <reference lib="esnext" /> /// <reference lib="webworker" /> const sw = /** @type {ServiceWorkerGlobalScope} */ (/** @type {unknown} */ (self)); ``` ```generated-ts /// <reference types="@sveltejs/kit" /> /// <reference no-default-lib="true"/> /// <reference lib="esnext" /> /// <reference lib="webworker" /> const sw = self as unknown as ServiceWorkerGlobalScope; ``` This disables access to DOM typings like `HTMLElement` which are not available inside a service worker and instantiates the correct globals. The reassignment of `self` to `sw` allows you to type cast it in the process (there are a couple of ways to do this, but this is the easiest that requires no additional files). Use `sw` instead of `self` in the rest of the file. The reference to the SvelteKit types ensures that the `$service-worker` import has proper type definitions. If you import `$env/static/public` you either have to `// @ts-ignore` the import or add `/// <reference types="../.svelte-kit/ambient.d.ts" />` to the reference types. ## Other solutions SvelteKit's service worker implementation is deliberately low-level. If you need a more full-fledged but also more opinionated solution, we recommend looking at solutions like [Vite PWA plugin](https://vite-pwa-org.netlify.app/frameworks/sveltekit.html), which uses [Workbox](https://web.dev/learn/pwa/workbox). For more general information on service workers, we recommend [the MDN web docs](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers).

# Server-only modules

Like a good friend, SvelteKit keeps your secrets. When writing your backend and frontend in the same repository, it can be easy to accidentally import sensitive data into your front-end code (environment variables containing API keys, for example). SvelteKit provides a way to prevent this entirely: server-only modules. ## Private environment variables The [`$env/static/private`]($env-static-private) and [`$env/dynamic/private`]($env-dynamic-private) modules can only be imported into modules that only run on the server, such as [`hooks.server.js`](hooks#Server-hooks) or [`+page.server.js`](routing#page-page.server.js). ## Server-only utilities The [`$app/server`]($app-server) module, which contains a [`read`]($app-server#read) function for reading assets from the filesystem, can likewise only be imported by code that runs on the server. ## Your modules You can make your own modules server-only in two ways: - adding `.server` to the filename, e.g. `secrets.server.js` - placing them in `$lib/server`, e.g. `$lib/server/secrets.js` ## How it works Any time you have public-facing code that imports server-only code (whether directly or indirectly)... ```js // @errors: 7005 /// file: $lib/server/secrets.js export const atlantisCoordinates = [/* redacted */]; ``` ```js // @errors: 2307 7006 7005 /// 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 <script> import { add } from './utils.js'; </script> ``` ...SvelteKit will error: ``` Cannot import $lib/server/secrets.js into public-facing code: - src/routes/+page.svelte - src/routes/utils.js - $lib/server/secrets.js ``` Even though the public-facing code — `src/routes/+page.svelte` — only uses the `add` export and not the secret `atlantisCoordinates` export, the secret code could end up in JavaScript that the browser downloads, and so the import chain is considered unsafe. This feature also works with dynamic imports, even interpolated ones like ``await import(`./${foo}.js`)``, with one small caveat: during development, if there are two or more dynamic imports between the public-facing code and the server-only module, the illegal import will not be detected the first time the code is loaded. ## Further reading - [Tutorial: Environment variables](/tutorial/kit/env-static-private)

# Snapshots

Ephemeral DOM state — like scroll positions on sidebars, the content of `<input>` elements and so on — is discarded when you navigate from one page to another. For example, if the user fills out a form but navigates away and then back before submitting, or if the user refreshes the page, the values they filled in will be lost. In cases where it's valuable to preserve that input, you can take a _snapshot_ of DOM state, which can then be restored if the user navigates back. To do this, export a `snapshot` object with `capture` and `restore` methods from a `+page.svelte` or `+layout.svelte`: ```svelte <!--- file: +page.svelte ---> <script> let comment = $state(''); /** @type {import('./$types').Snapshot<string>} */ export const snapshot = { capture: () => comment, restore: (value) => comment = value }; </script> <form method="POST"> <label for="comment">Comment</label> <textarea id="comment" bind:value={comment} /> <button>Post comment</button> </form> ``` When you navigate away from this page, the `capture` function is called immediately before the page updates, and the returned value is associated with the current entry in the browser's history stack. If you navigate back, the `restore` function is called with the stored value as soon as the page is updated. The data must be serializable as JSON so that it can be persisted to `sessionStorage`. This allows the state to be restored when the page is reloaded, or when the user navigates back from a different site.

# Shallow routing

As you navigate around a SvelteKit app, you create _history entries_. Clicking the back and forward buttons traverses through this list of entries, re-running any `load` functions and replacing page components as necessary. Sometimes, it's useful to create history entries _without_ navigating. For example, you might want to show a modal dialog that the user can dismiss by navigating back. This is particularly valuable on mobile devices, where swipe gestures are often more natural than interacting directly with the UI. In these cases, a modal that is _not_ associated with a history entry can be a source of frustration, as a user may swipe backwards in an attempt to dismiss it and find themselves on the wrong page. SvelteKit makes this possible with the [`pushState`]($app-navigation#pushState) and [`replaceState`]($app-navigation#replaceState) functions, which allow you to associate state with a history entry without navigating. For example, to implement a history-driven modal: ```svelte <!--- file: +page.svelte ---> <script> import { pushState } from '$app/navigation'; import { page } from '$app/state'; import Modal from './Modal.svelte'; function showModal() { pushState('', { showModal: true }); } </script> {#if page.state.showModal} <Modal close={() => history.back()} /> {/if} ``` The modal can be dismissed by navigating back (unsetting `page.state.showModal`) or by interacting with it in a way that causes the `close` callback to run, which will navigate back programmatically. ## API The first argument to `pushState` is the URL, relative to the current URL. To stay on the current URL, use `''`. The second argument is the new page state, which can be accessed via the [page object]($app-state#page) as `page.state`. You can make page state type-safe by declaring an [`App.PageState`](types#PageState) interface (usually in `src/app.d.ts`). To set page state without creating a new history entry, use `replaceState` instead of `pushState`. > `page.state` from `$app/state` was added in SvelteKit 2.12. If you're using an earlier version or are using Svelte 4, use `$page.state` from `$app/stores` instead. ## Loading data for a route When shallow routing, you may want to render another `+page.svelte` inside the current page. For example, clicking on a photo thumbnail could pop up the detail view without navigating to the photo page. For this to work, you need to load the data that the `+page.svelte` expects. A convenient way to do this is to use [`preloadData`]($app-navigation#preloadData) inside the `click` handler of an `<a>` element. If the element (or a parent) uses [`data-sveltekit-preload-data`](link-options#data-sveltekit-preload-data), the data will have already been requested, and `preloadData` will reuse that request. ```svelte <!--- file: src/routes/photos/+page.svelte ---> <script> import { preloadData, pushState, goto } from '$app/navigation'; import { page } from '$app/state'; import Modal from './Modal.svelte'; import PhotoPage from './[id]/+page.svelte'; let { data } = $props(); </script> {#each data.thumbnails as thumbnail} <a href="/photos/{thumbnail.id}" onclick={async (e) => { if (innerWidth < 640 // bail if the screen is too small || e.shiftKey // or the link is opened in a new window || e.metaKey || e.ctrlKey // or a new tab (mac: metaKey, win/linux: ctrlKey) // should also consider clicking with a mouse scroll wheel ) return; // prevent navigation e.preventDefault(); const { href } = e.currentTarget; // run `load` functions (or rather, get the result of the `load` functions // that are already running because of `data-sveltekit-preload-data`) const result = await preloadData(href); if (result.type === 'loaded' && result.status === 200) { pushState(href, { selected: result.data }); } else { // something bad happened! try navigating goto(href); } }} > <img alt={thumbnail.alt} src={thumbnail.src} /> </a> {/each} {#if page.state.selected} <Modal onclose={() => history.back()}> <!-- pass page data to the +page.svelte component, just like SvelteKit would on navigation --> <PhotoPage data={page.state.selected} /> </Modal> {/if} ``` ## Caveats During server-side rendering, `page.state` is always an empty object. The same is true for the first page the user lands on — if the user reloads the page (or returns from another document), state will _not_ be applied until they navigate. Shallow routing is a feature that requires JavaScript to work. Be mindful when using it and try to think of sensible fallback behavior in case JavaScript isn't available.

# Auth

Auth refers to authentication and authorization, which are common needs when building a web application. Authentication means verifying that the user is who they say they are based on their provided credentials. Authorization means determining which actions they are allowed to take. ## Sessions vs tokens After the user has provided their credentials such as a username and password, we want to allow them to use the application without needing to provide their credentials again for future requests. Users are commonly authenticated on subsequent requests with either a session identifier or signed token such as a JSON Web Token (JWT). Session IDs are most commonly stored in a database. They can be immediately revoked, but require a database query to be made on each request. In contrast, JWT generally are not checked against a datastore, which means they cannot be immediately revoked. The advantage of this method is improved latency and reduced load on your datastore. ## Integration points Auth [cookies](@sveltejs-kit#Cookies) can be checked inside [server hooks](hooks#Server-hooks). If a user is found matching the provided credentials, the user information can be stored in [`locals`](hooks#Server-hooks-handle). ## Guides [Lucia](https://lucia-auth.com/) is a good reference for session-based web app auth. It contains example code snippets and projects for implementing session-based auth within SvelteKit and other JS projects. You can add code which follows the Lucia guide to your project with `npx sv create` when creating a new project or `npx sv add lucia` for an existing project. An auth system is tightly coupled to a web framework because most of the code lies in validating user input, handling errors, and directing users to the appropriate next page. As a result, many of the generic JS auth libraries include one or more web frameworks within them. For this reason, many users will find it preferrable to follow a SvelteKit-specific guide such as the examples found in [Lucia](https://lucia-auth.com/) rather than having multiple web frameworks inside their project.

# Images

Images can have a big impact on your app's performance. For best results, you should optimize them by doing the following: - generate optimal formats like `.avif` and `.webp` - create different sizes for different screens - ensure that assets can be cached effectively Doing this manually is tedious. There are a variety of techniques you can use, depending on your needs and preferences. ## Vite's built-in handling [Vite will automatically process imported assets](https://vitejs.dev/guide/assets.html) for improved performance. This includes assets referenced via the CSS `url()` function. Hashes will be added to the filenames so that they can be cached, and assets smaller than `assetsInlineLimit` will be inlined. Vite's asset handling is most often used for images, but is also useful for video, audio, etc. ```svelte <script> import logo from '$lib/assets/logo.png'; </script> <img alt="The project logo" src={logo} /> ``` ## @sveltejs/enhanced-img `@sveltejs/enhanced-img` is a plugin offered on top of Vite's built-in asset handling. It provides plug and play image processing that serves smaller file formats like `avif` or `webp`, automatically sets the intrinsic `width` and `height` of the image to avoid layout shift, creates images of multiple sizes for various devices, and strips EXIF data for privacy. It will work in any Vite-based project including, but not limited to, SvelteKit projects. > > **WARNING**: The `@sveltejs/enhanced-img` package is experimental. It uses pre-1.0 versioning and may introduce breaking changes with every minor version release. ### Setup Install: ```bash npm install --save-dev @sveltejs/enhanced-img ``` Adjust `vite.config.js`: ```js import { sveltekit } from '@sveltejs/kit/vite'; +++import { enhancedImages } from '@sveltejs/enhanced-img';+++ import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ +++enhancedImages(),+++ sveltekit() ] }); ``` Building will take longer on the first build due to the computational expense of transforming images. However, the build output will be cached in `./node_modules/.cache/imagetools` so that subsequent builds will be fast. ### Basic usage Use in your `.svelte` components by using `<enhanced:img>` rather than `<img>` and referencing the image file with a [Vite asset import](https://vitejs.dev/guide/assets.html#static-asset-handling) path: ```svelte <enhanced:img src="./path/to/your/image.jpg" alt="An alt text" /> ``` At build time, your `<enhanced:img>` tag will be replaced with an `<img>` wrapped by a `<picture>` providing multiple image types and sizes. It's only possible to downscale images without losing quality, which means that you should provide the highest resolution image that you need — smaller versions will be generated for the various device types that may request an image. You should provide your image at 2x resolution for HiDPI displays (a.k.a. retina displays). `<enhanced:img>` will automatically take care of serving smaller versions to smaller devices. If you wish to add styles to your `<enhanced:img>`, you should add a `class` and target that. ### Dynamically choosing an image You can also manually import an image asset and pass it to an `<enhanced:img>`. This is useful when you have a collection of static images and would like to dynamically choose one or [iterate over them](https://github.com/sveltejs/kit/blob/0ab1733e394b6310895a1d3bf0f126ce34531170/sites/kit.svelte.dev/src/routes/home/Showcase.svelte). In this case you will need to update both the `import` statement and `<img>` element as shown below to indicate you'd like process them. ```svelte <script> import MyImage from './path/to/your/image.jpg?enhanced'; </script> <enhanced:img src={MyImage} alt="some alt text" /> ``` You can also use [Vite's `import.meta.glob`](https://vitejs.dev/guide/features.html#glob-import). Note that you will have to specify `enhanced` via a [custom query](https://vitejs.dev/guide/features.html#custom-queries): ```svelte <script> const imageModules = import.meta.glob( '/path/to/assets/*.{avif,gif,heif,jpeg,jpg,png,tiff,webp,svg}', { eager: true, query: { enhanced: true } } ) </script> {#each Object.entries(imageModules) as [_path, module]} <enhanced:img src={module.default} alt="some alt text" /> {/each} ``` ### Intrinsic Dimensions `width` and `height` are optional as they can be inferred from the source image and will be automatically added when the `<enhanced:img>` tag is preprocessed. With these attributes, the browser can reserve the correct amount of space, preventing [layout shift](https://web.dev/articles/cls). If you'd like to use a different `width` and `height` you can style the image with CSS. Because the preprocessor adds a `width` and `height` for you, if you'd like one of the dimensions to be automatically calculated then you will need to specify that: ```svelte <style> .hero-image img { width: var(--size); height: auto; } </style> ``` ### `srcset` and `sizes` If you have a large image, such as a hero image taking the width of the design, you should specify `sizes` so that smaller versions are requested on smaller devices. E.g. if you have a 1280px image you may want to specify something like: ```svelte <enhanced:img src="./image.png" sizes="min(1280px, 100vw)"/> ``` If `sizes` is specified, `<enhanced:img>` will generate small images for smaller devices and populate the `srcset` attribute. The smallest picture generated automatically will have a width of 540px. If you'd like smaller images or would otherwise like to specify custom widths, you can do that with the `w` query parameter: ```svelte <enhanced:img src="./image.png?w=1280;640;400" sizes="(min-width:1920px) 1280px, (min-width:1080px) 640px, (min-width:768px) 400px" /> ``` If `sizes` is not provided, then a HiDPI/Retina image and a standard resolution image will be generated. The image you provide should be 2x the resolution you wish to display so that the browser can display that image on devices with a high [device pixel ratio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio). ### Per-image transforms By default, enhanced images will be transformed to more efficient formats. However, you may wish to apply other transforms such as a blur, quality, flatten, or rotate operation. You can run per-image transforms by appending a query string: ```svelte <enhanced:img src="./path/to/your/image.jpg?blur=15" alt="An alt text" /> ``` [See the imagetools repo for the full list of directives](https://github.com/JonasKruckenberg/imagetools/blob/main/docs/directives.md). ## Loading images dynamically from a CDN In some cases, the images may not be accessible at build time — e.g. they may live inside a content management system or elsewhere. Using a content delivery network (CDN) can allow you to optimize these images dynamically, and provides more flexibility with regards to sizes, but it may involve some setup overhead and usage costs. Depending on caching strategy, the browser may not be able to use a cached copy of the asset until a [304 response](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304) is received from the CDN. Building HTML to target CDNs allows using an `<img>` tag since the CDN can serve the appropriate format based on the `User-Agent` header, whereas build-time optimizations must produce `<picture>` tags with multiple sources. Finally, some CDNs may generate images lazily, which could have a negative performance impact for sites with low traffic and frequently changing images. CDNs can generally be used without any need for a library. However, there are a number of libraries with Svelte support that make it easier. [`@unpic/svelte`](https://unpic.pics/img/svelte/) is a CDN-agnostic library with support for a large number of providers. You may also find that specific CDNs like [Cloudinary](https://svelte.cloudinary.dev/) have Svelte support. Finally, some content management systems (CMS) which support Svelte (such as [Contentful](https://www.contentful.com/sveltekit-starter-guide/), [Storyblok](https://github.com/storyblok/storyblok-svelte), and [Contentstack](https://www.contentstack.com/docs/developers/sample-apps/build-a-starter-website-with-sveltekit-and-contentstack)) have built-in support for image handling. ## Icons A great way to use icons is to define them purely in CSS. Iconify offers a huge set of icons [available via CSS](https://iconify.design/docs/usage/css/). For icons defined in `.svelte` files, it is recommended to avoid libraries that provide a `.svelte` file per icon. These libraries can have thousands of `.svelte` files which really slow down Vite's dependency optimization. This can become especially pathological if the icons are imported both via an umbrella import and subpath import [as described in the `vite-plugin-svelte` FAQ](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies). ## Best practices - For each image type, use the appropriate solution from those discussed above. You can mix and match all three solutions in one project. For example, you may use Vite's built-in handling to provide images for `<meta>` tags, display images on your homepage with `@sveltejs/enhanced-img`, and display user-submitted content with a dynamic approach. - Consider serving all images via CDN regardless of the image optimization types you use. CDNs reduce latency by distributing copies of static assets globally. - Your original images should have a good quality/resolution and should have 2x the width it will be displayed at to serve HiDPI devices. Image processing can size images down to save bandwidth when serving smaller screens, but it would be a waste of bandwidth to invent pixels to size images up. - For images which are much larger than the width of a mobile device (roughly 400px), such as a hero image taking the width of the page design, specify `sizes` so that smaller images can be served on smaller devices. - For important images, such as the [largest contentful paint (LCP)](https://web.dev/articles/lcp) image, set `fetchpriority="high"` and avoid `loading="lazy"` to prioritize loading as early as possible. - Give the image a container or styling so that it is constrained and does not jump around while the page is loading affecting your [cumulative layout shift (CLS)](https://web.dev/articles/cls). `width` and `height` help the browser to reserve space while the image is still loading, so `@sveltejs/enhanced-img` will add a `width` and `height` for you. - Always provide a good `alt` text. The Svelte compiler will warn you if you don't do this. - Do not use `em` or `rem` in `sizes` and change the default size of these measures. When used in `sizes` or `@media` queries, `em` and `rem` are both defined to mean the user's default `font-size`. For a `sizes` declaration like `sizes="(min-width: 768px) min(100vw, 108rem), 64rem"`, the actual `em` or `rem` that controls how the image is laid out on the page can be different if changed by CSS. For example, do not do something like `html { font-size: 62.5%; }` as the slot reserved by the browser preloader will now end up being larger than the actual slot of the CSS object model once it has been created.

# Accessibility

SvelteKit strives to provide an accessible platform for your app by default. Svelte's [compile-time accessibility checks](../svelte/compiler-warnings) will also apply to any SvelteKit application you build. Here's how SvelteKit's built-in accessibility features work and what you need to do to help these features to work as well as possible. Keep in mind that while SvelteKit provides an accessible foundation, you are still responsible for making sure your application code is accessible. If you're new to accessibility, see the ["further reading"](accessibility#Further-reading) section of this guide for additional resources. We recognize that accessibility can be hard to get right. If you want to suggest improvements to how SvelteKit handles accessibility, please [open a GitHub issue](https://github.com/sveltejs/kit/issues). ## Route announcements In traditional server-rendered applications, every navigation (e.g. clicking on an `<a>` tag) triggers a full page reload. When this happens, screen readers and other assistive technology will read out the new page's title so that users understand that the page has changed. Since navigation between pages in SvelteKit happens without reloading the page (known as [client-side routing](glossary#Routing)), SvelteKit injects a [live region](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) onto the page that will read out the new page name after each navigation. This determines the page name to announce by inspecting the `<title>` element. Because of this behavior, every page in your app should have a unique, descriptive title. In SvelteKit, you can do this by placing a `<svelte:head>` element on each page: ```svelte <!--- file: src/routes/+page.svelte ---> <svelte:head> <title>Todo List</title> </svelte:head> ``` This will allow screen readers and other assistive technology to identify the new page after a navigation occurs. Providing a descriptive title is also important for [SEO](seo#Manual-setup-title-and-meta). ## Focus management In traditional server-rendered applications, every navigation will reset focus to the top of the page. This ensures that people browsing the web with a keyboard or screen reader will start interacting with the page from the beginning. To simulate this behavior during client-side routing, SvelteKit focuses the `<body>` element after each navigation and [enhanced form submission](form-actions#Progressive-enhancement). There is one exception - if an element with the [`autofocus`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) attribute is present, SvelteKit will focus that element instead. Make sure to [consider the implications for assistive technology](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus#accessibility_considerations) when using that attribute. If you want to customize SvelteKit's focus management, you can use the `afterNavigate` hook: ```js /// <reference types="@sveltejs/kit" /> // ---cut--- import { afterNavigate } from '$app/navigation'; afterNavigate(() => { /** @type {HTMLElement | null} */ const to_focus = document.querySelector('.focus-me'); to_focus?.focus(); }); ``` You can also programmatically navigate to a different page using the [`goto`]($app-navigation#goto) function. By default, this will have the same client-side routing behavior as clicking on a link. However, `goto` also accepts a `keepFocus` option that will preserve the currently-focused element instead of resetting focus. If you enable this option, make sure the currently-focused element still exists on the page after navigation. If the element no longer exists, the user's focus will be lost, making for a confusing experience for assistive technology users. ## The "lang" attribute By default, SvelteKit's page template sets the default language of the document to English. If your content is not in English, you should update the `<html>` element in `src/app.html` to have the correct [`lang`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang#accessibility) attribute. This will ensure that any assistive technology reading the document uses the correct pronunciation. For example, if your content is in German, you should update `app.html` to the following: ```html /// file: src/app.html <html lang="de"> ``` If your content is available in multiple languages, you should set the `lang` attribute based on the language of the current page. You can do this with SvelteKit's [handle hook](hooks#Server-hooks-handle): ```html /// file: src/app.html <html lang="%lang%"> ``` ```js /// file: src/hooks.server.js /** * @param {import('@sveltejs/kit').RequestEvent} event */ function get_lang(event) { return 'en'; } // ---cut--- /** @type {import('@sveltejs/kit').Handle} */ export function handle({ event, resolve }) { return resolve(event, { transformPageChunk: ({ html }) => html.replace('%lang%', get_lang(event)) }); } ``` ## Further reading For the most part, building an accessible SvelteKit app is the same as building an accessible web app. You should be able to apply information from the following general accessibility resources to any web experience you build: - [MDN Web Docs: Accessibility](https://developer.mozilla.org/en-US/docs/Learn/Accessibility) - [The A11y Project](https://www.a11yproject.com/) - [How to Meet WCAG (Quick Reference)](https://www.w3.org/WAI/WCAG21/quickref/)

# SEO

The most important aspect of SEO is to create high-quality content that is widely linked to from around the web. However, there are a few technical considerations for building sites that rank well. ## Out of the box ### SSR While search engines have got better in recent years at indexing content that was rendered with client-side JavaScript, server-side rendered content is indexed more frequently and reliably. SvelteKit employs SSR by default, and while you can disable it in [`handle`](hooks#Server-hooks-handle), you should leave it on unless you have a good reason not to. ### Performance Signals such as [Core Web Vitals](https://web.dev/vitals/#core-web-vitals) impact search engine ranking. Because Svelte and SvelteKit introduce minimal overhead, it's easier to build high performance sites. You can test your site's performance using Google's [PageSpeed Insights](https://pagespeed.web.dev/) or [Lighthouse](https://developers.google.com/web/tools/lighthouse). Read [the performance page](performance) for more details. ### Normalized URLs SvelteKit redirects pathnames with trailing slashes to ones without (or vice versa depending on your [configuration](page-options#trailingSlash)), as duplicate URLs are bad for SEO. ## Manual setup ### &lt;title&gt; and &lt;meta&gt; Every page should have well-written and unique `<title>` and `<meta name="description">` elements inside a [`<svelte:head>`](../svelte/svelte-head). Guidance on how to write descriptive titles and descriptions, along with other suggestions on making content understandable by search engines, can be found on Google's [Lighthouse SEO audits](https://web.dev/lighthouse-seo/) documentation. ### Sitemaps [Sitemaps](https://developers.google.com/search/docs/advanced/sitemaps/build-sitemap) help search engines prioritize pages within your site, particularly when you have a large amount of content. You can create a sitemap dynamically using an endpoint: ```js /// file: src/routes/sitemap.xml/+server.js export async function GET() { return new Response( ` <?xml version="1.0" encoding="UTF-8" ?> <urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="https://www.w3.org/1999/xhtml" xmlns:mobile="https://www.google.com/schemas/sitemap-mobile/1.0" xmlns:news="https://www.google.com/schemas/sitemap-news/0.9" xmlns:image="https://www.google.com/schemas/sitemap-image/1.1" xmlns:video="https://www.google.com/schemas/sitemap-video/1.1" > <!-- <url> elements go here --> </urlset>`.trim(), { headers: { 'Content-Type': 'application/xml' } } ); } ``` ### AMP An unfortunate reality of modern web development is that it is sometimes necessary to create an [Accelerated Mobile Pages (AMP)](https://amp.dev/) version of your site. In SvelteKit this can be done by setting the [`inlineStyleThreshold`](configuration#inlineStyleThreshold) option... ```js /// file: svelte.config.js /** @type {import('@sveltejs/kit').Config} */ const config = { kit: { // since <link rel="stylesheet"> isn't // allowed, inline all styles inlineStyleThreshold: Infinity } }; export default config; ``` ...disabling `csr` in your root `+layout.js`/`+layout.server.js`... ```js /// file: src/routes/+layout.server.js export const csr = false; ``` ...adding `amp` to your `app.html` ```html <html amp> ... ``` ...and transforming the HTML using `transformPageChunk` along with `transform` imported from `@sveltejs/amp`: ```js /// file: src/hooks.server.js import * as amp from '@sveltejs/amp'; /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { let buffer = ''; return await resolve(event, { transformPageChunk: ({ html, done }) => { buffer += html; if (done) return amp.transform(buffer); } }); } ``` To prevent shipping any unused CSS as a result of transforming the page to amp, we can use [`dropcss`](https://www.npmjs.com/package/dropcss): ```js // @filename: ambient.d.ts declare module 'dropcss'; // @filename: index.js // ---cut--- /// file: src/hooks.server.js // @errors: 2307 import * as amp from '@sveltejs/amp'; import dropcss from 'dropcss'; /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { let buffer = ''; return await resolve(event, { transformPageChunk: ({ html, done }) => { buffer += html; if (done) { let css = ''; const markup = amp .transform(buffer) .replace('⚡', 'amp') // dropcss can't handle this character .replace(/<style amp-custom([^>]*?)>([^]+?)<\/style>/, (match, attributes, contents) => { css = contents; return `<style amp-custom${attributes}></style>`; }); css = dropcss({ css, html: markup }).css; return markup.replace('</style>', `${css}</style>`); } } }); } ```

# @sveltejs/kit

```js // @noErrors import { Server, VERSION, error, fail, isActionFailure, isHttpError, isRedirect, json, normalizeUrl, redirect, text } from '@sveltejs/kit'; ``` ## Server <div class="ts-block"> ```dts class Server {/*…*/} ``` <div class="ts-block-property"> ```dts constructor(manifest: SSRManifest); ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts init(options: ServerInitOptions): Promise<void>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts respond(request: Request, options: RequestOptions): Promise<Response>; ``` <div class="ts-block-property-details"></div> </div></div> ## VERSION <div class="ts-block"> ```dts const VERSION: string; ``` </div> ## error Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking `handleError`. Make sure you're not catching the thrown error, which would prevent SvelteKit from handling it. <div class="ts-block"> ```dts function error(status: number, body: App.Error): never; ``` </div> <div class="ts-block"> ```dts function error( status: number, body?: { message: string; } extends App.Error ? App.Error | string | undefined : never ): never; ``` </div> ## fail Create an `ActionFailure` object. <div class="ts-block"> ```dts function fail(status: number): ActionFailure<undefined>; ``` </div> <div class="ts-block"> ```dts function fail< T extends Record<string, unknown> | undefined = undefined >(status: number, data: T): ActionFailure<T>; ``` </div> ## isActionFailure Checks whether this is an action failure thrown by `fail`. <div class="ts-block"> ```dts function isActionFailure(e: unknown): e is ActionFailure; ``` </div> ## isHttpError Checks whether this is an error thrown by `error`. <div class="ts-block"> ```dts function isHttpError<T extends number>( e: unknown, status?: T | undefined ): e is HttpError_1 & { status: T extends undefined ? never : T; }; ``` </div> ## isRedirect Checks whether this is a redirect thrown by `redirect`. <div class="ts-block"> ```dts function isRedirect(e: unknown): e is Redirect_1; ``` </div> ## json Create a JSON `Response` object from the supplied data. <div class="ts-block"> ```dts function json( data: any, init?: ResponseInit | undefined ): Response; ``` </div> ## normalizeUrl <blockquote class="since note"> Available since 2.18.0 </blockquote> Strips possible SvelteKit-internal suffixes and trailing slashes from the URL pathname. Returns the normalized URL as well as a method for adding the potential suffix back based on a new pathname (possibly including search) or URL. ```js // @errors: 7031 import { normalizeUrl } from '@sveltejs/kit'; const { url, denormalize } = normalizeUrl('/blog/post/__data.json'); console.log(url.pathname); // /blog/post console.log(denormalize('/blog/post/a')); // /blog/post/a/__data.json ``` <div class="ts-block"> ```dts function normalizeUrl(url: URL | string): { url: URL; wasNormalized: boolean; denormalize: (url?: string | URL) => URL; }; ``` </div> ## redirect Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you're not catching the thrown redirect, which would prevent SvelteKit from handling it. Most common status codes: * `303 See Other`: redirect as a GET request (often used after a form POST request) * `307 Temporary Redirect`: redirect will keep the request method * `308 Permanent Redirect`: redirect will keep the request method, SEO will be transferred to the new page [See all redirect status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages) <div class="ts-block"> ```dts function redirect( status: | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL ): never; ``` </div> ## text Create a `Response` object from the supplied body. <div class="ts-block"> ```dts function text( body: string, init?: ResponseInit | undefined ): Response; ``` </div> ## Action Shape of a form action method that is part of `export const actions = {..}` in `+page.server.js`. See [form actions](/docs/kit/form-actions) for more information. <div class="ts-block"> ```dts type Action< Params extends Partial<Record<string, string>> = Partial< Record<string, string> >, OutputData extends Record<string, any> | void = Record< string, any > | void, RouteId extends string | null = string | null > = ( event: RequestEvent<Params, RouteId> ) => MaybePromise<OutputData>; ``` </div> ## ActionFailure <div class="ts-block"> ```dts interface ActionFailure< T extends Record<string, unknown> | undefined = undefined > {/*…*/} ``` <div class="ts-block-property"> ```dts status: number; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts data: T; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts [uniqueSymbol]: true; ``` <div class="ts-block-property-details"></div> </div></div> ## ActionResult When calling a form action via fetch, the response will be one of these shapes. ```svelte <form method="post" use:enhance={() => { return ({ result }) => { // result is of type ActionResult }; }} ``` <div class="ts-block"> ```dts type ActionResult< Success extends | Record<string, unknown> | undefined = Record<string, any>, Failure extends | Record<string, unknown> | undefined = Record<string, any> > = | { type: 'success'; status: number; data?: Success } | { type: 'failure'; status: number; data?: Failure } | { type: 'redirect'; status: number; location: string } | { type: 'error'; status?: number; error: any }; ``` </div> ## Actions Shape of the `export const actions = {..}` object in `+page.server.js`. See [form actions](/docs/kit/form-actions) for more information. <div class="ts-block"> ```dts type Actions< Params extends Partial<Record<string, string>> = Partial< Record<string, string> >, OutputData extends Record<string, any> | void = Record< string, any > | void, RouteId extends string | null = string | null > = Record<string, Action<Params, OutputData, RouteId>>; ``` </div> ## Adapter [Adapters](/docs/kit/adapters) are responsible for taking the production build and turning it into something that can be deployed to a platform of your choosing. <div class="ts-block"> ```dts interface Adapter {/*…*/} ``` <div class="ts-block-property"> ```dts name: string; ``` <div class="ts-block-property-details"> The name of the adapter, using for logging. Will typically correspond to the package name. </div> </div> <div class="ts-block-property"> ```dts adapt: (builder: Builder) => MaybePromise<void>; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `builder` An object provided by SvelteKit that contains methods for adapting the app </div> This function is called after SvelteKit has built your app. </div> </div> <div class="ts-block-property"> ```dts supports?: {/*…*/} ``` <div class="ts-block-property-details"> Checks called during dev and build to determine whether specific features will work in production with this adapter <div class="ts-block-property-children"><div class="ts-block-property"> ```dts read?: (details: { config: any; route: { id: string } }) => boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `config` The merged route config </div> Test support for `read` from `$app/server` </div> </div></div> </div> </div> <div class="ts-block-property"> ```dts emulate?: () => MaybePromise<Emulator>; ``` <div class="ts-block-property-details"> Creates an `Emulator`, which allows the adapter to influence the environment during dev, build and prerendering </div> </div></div> ## AfterNavigate The argument passed to [`afterNavigate`](/docs/kit/$app-navigation#afterNavigate) callbacks. <div class="ts-block"> ```dts interface AfterNavigate extends Omit<Navigation, 'type'> {/*…*/} ``` <div class="ts-block-property"> ```dts type: Exclude<NavigationType, 'leave'>; ``` <div class="ts-block-property-details"> The type of navigation: - `enter`: The app has hydrated - `form`: The user submitted a `<form>` - `link`: Navigation was triggered by a link click - `goto`: Navigation was triggered by a `goto(...)` call or a redirect - `popstate`: Navigation was triggered by back/forward navigation </div> </div> <div class="ts-block-property"> ```dts willUnload: false; ``` <div class="ts-block-property-details"> Since `afterNavigate` callbacks are called after a navigation completes, they will never be called with a navigation that unloads the page. </div> </div></div> ## AwaitedActions <div class="ts-block"> ```dts type AwaitedActions< T extends Record<string, (...args: any) => any> > = OptionalUnion< { [Key in keyof T]: UnpackValidationError< Awaited<ReturnType<T[Key]>> >; }[keyof T] >; ``` </div> ## BeforeNavigate The argument passed to [`beforeNavigate`](/docs/kit/$app-navigation#beforeNavigate) callbacks. <div class="ts-block"> ```dts interface BeforeNavigate extends Navigation {/*…*/} ``` <div class="ts-block-property"> ```dts cancel: () => void; ``` <div class="ts-block-property-details"> Call this to prevent the navigation from starting. </div> </div></div> ## Builder This object is passed to the `adapt` function of adapters. It contains various methods and properties that are useful for adapting the app. <div class="ts-block"> ```dts interface Builder {/*…*/} ``` <div class="ts-block-property"> ```dts log: Logger; ``` <div class="ts-block-property-details"> Print messages to the console. `log.info` and `log.minor` are silent unless Vite's `logLevel` is `info`. </div> </div> <div class="ts-block-property"> ```dts rimraf: (dir: string) => void; ``` <div class="ts-block-property-details"> Remove `dir` and all its contents. </div> </div> <div class="ts-block-property"> ```dts mkdirp: (dir: string) => void; ``` <div class="ts-block-property-details"> Create `dir` and any required parent directories. </div> </div> <div class="ts-block-property"> ```dts config: ValidatedConfig; ``` <div class="ts-block-property-details"> The fully resolved `svelte.config.js`. </div> </div> <div class="ts-block-property"> ```dts prerendered: Prerendered; ``` <div class="ts-block-property-details"> Information about prerendered pages and assets, if any. </div> </div> <div class="ts-block-property"> ```dts routes: RouteDefinition[]; ``` <div class="ts-block-property-details"> An array of all routes (including prerendered) </div> </div> <div class="ts-block-property"> ```dts createEntries: (fn: (route: RouteDefinition) => AdapterEntry) => Promise<void>; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `fn` A function that groups a set of routes into an entry point - <span class="tag deprecated">deprecated</span> Use `builder.routes` instead </div> Create separate functions that map to one or more routes of your app. </div> </div> <div class="ts-block-property"> ```dts findServerAssets: (routes: RouteDefinition[]) => string[]; ``` <div class="ts-block-property-details"> Find all the assets imported by server files belonging to `routes` </div> </div> <div class="ts-block-property"> ```dts generateFallback: (dest: string) => Promise<void>; ``` <div class="ts-block-property-details"> Generate a fallback page for a static webserver to use when no route is matched. Useful for single-page apps. </div> </div> <div class="ts-block-property"> ```dts generateEnvModule: () => void; ``` <div class="ts-block-property-details"> Generate a module exposing build-time environment variables as `$env/dynamic/public`. </div> </div> <div class="ts-block-property"> ```dts generateManifest: (opts: { relativePath: string; routes?: RouteDefinition[] }) => string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `opts` a relative path to the base directory of the app and optionally in which format (esm or cjs) the manifest should be generated </div> Generate a server-side manifest to initialise the SvelteKit [server](/docs/kit/@sveltejs-kit#Server) with. </div> </div> <div class="ts-block-property"> ```dts getBuildDirectory: (name: string) => string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `name` path to the file, relative to the build directory </div> Resolve a path to the `name` directory inside `outDir`, e.g. `/path/to/.svelte-kit/my-adapter`. </div> </div> <div class="ts-block-property"> ```dts getClientDirectory: () => string; ``` <div class="ts-block-property-details"> Get the fully resolved path to the directory containing client-side assets, including the contents of your `static` directory. </div> </div> <div class="ts-block-property"> ```dts getServerDirectory: () => string; ``` <div class="ts-block-property-details"> Get the fully resolved path to the directory containing server-side code. </div> </div> <div class="ts-block-property"> ```dts getAppPath: () => string; ``` <div class="ts-block-property-details"> Get the application path including any configured `base` path, e.g. `my-base-path/_app`. </div> </div> <div class="ts-block-property"> ```dts writeClient: (dest: string) => string[]; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `dest` the destination folder - <span class="tag">returns</span> an array of files written to `dest` </div> Write client assets to `dest`. </div> </div> <div class="ts-block-property"> ```dts writePrerendered: (dest: string) => string[]; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `dest` the destination folder - <span class="tag">returns</span> an array of files written to `dest` </div> Write prerendered files to `dest`. </div> </div> <div class="ts-block-property"> ```dts writeServer: (dest: string) => string[]; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `dest` the destination folder - <span class="tag">returns</span> an array of files written to `dest` </div> Write server-side code to `dest`. </div> </div> <div class="ts-block-property"> ```dts copy: ( from: string, to: string, opts?: { filter?(basename: string): boolean; replace?: Record<string, string>; } ) => string[]; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `from` the source file or directory - `to` the destination file or directory - `opts.filter` a function to determine whether a file or directory should be copied - `opts.replace` a map of strings to replace - <span class="tag">returns</span> an array of files that were copied </div> Copy a file or directory. </div> </div> <div class="ts-block-property"> ```dts compress: (directory: string) => Promise<void>; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `directory` The directory containing the files to be compressed </div> Compress files in `directory` with gzip and brotli, where appropriate. Generates `.gz` and `.br` files alongside the originals. </div> </div></div> ## ClientInit <blockquote class="since note"> Available since 2.10.0 </blockquote> The [`init`](/docs/kit/hooks#Shared-hooks-init) will be invoked once the app starts in the browser <div class="ts-block"> ```dts type ClientInit = () => MaybePromise<void>; ``` </div> ## Config See the [configuration reference](/docs/kit/configuration) for details. ## Cookies <div class="ts-block"> ```dts interface Cookies {/*…*/} ``` <div class="ts-block-property"> ```dts get: (name: string, opts?: import('cookie').CookieParseOptions) => string | undefined; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `name` the name of the cookie - `opts` the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) </div> Gets a cookie that was previously set with `cookies.set`, or from the request headers. </div> </div> <div class="ts-block-property"> ```dts getAll: (opts?: import('cookie').CookieParseOptions) => Array<{ name: string; value: string }>; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `opts` the options, passed directly to `cookie.parse`. See documentation [here](https://github.com/jshttp/cookie#cookieparsestr-options) </div> Gets all cookies that were previously set with `cookies.set`, or from the request headers. </div> </div> <div class="ts-block-property"> ```dts set: ( name: string, value: string, opts: import('cookie').CookieSerializeOptions & { path: string } ) => void; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `name` the name of the cookie - `value` the cookie value - `opts` the options, passed directly to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) </div> Sets a cookie. This will add a `set-cookie` header to the response, but also make the cookie available via `cookies.get` or `cookies.getAll` during the current request. The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The `sameSite` option defaults to `lax`. You must specify a `path` for the cookie. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children </div> </div> <div class="ts-block-property"> ```dts delete: (name: string, opts: import('cookie').CookieSerializeOptions & { path: string }) => void; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `name` the name of the cookie - `opts` the options, passed directly to `cookie.serialize`. The `path` must match the path of the cookie you want to delete. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) </div> Deletes a cookie by setting its value to an empty string and setting the expiry date in the past. You must specify a `path` for the cookie. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children </div> </div> <div class="ts-block-property"> ```dts serialize: ( name: string, value: string, opts: import('cookie').CookieSerializeOptions & { path: string } ) => string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `name` the name of the cookie - `value` the cookie value - `opts` the options, passed directly to `cookie.serialize`. See documentation [here](https://github.com/jshttp/cookie#cookieserializename-value-options) </div> Serialize a cookie name-value pair into a `Set-Cookie` header string, but don't apply it to the response. The `httpOnly` and `secure` options are `true` by default (except on http://localhost, where `secure` is `false`), and must be explicitly disabled if you want cookies to be readable by client-side JavaScript and/or transmitted over HTTP. The `sameSite` option defaults to `lax`. You must specify a `path` for the cookie. In most cases you should explicitly set `path: '/'` to make the cookie available throughout your app. You can use relative paths, or set `path: ''` to make the cookie only available on the current path and its children </div> </div></div> ## Emulator A collection of functions that influence the environment during dev, build and prerendering <div class="ts-block"> ```dts interface Emulator {/*…*/} ``` <div class="ts-block-property"> ```dts platform?(details: { config: any; prerender: PrerenderOption }): MaybePromise<App.Platform>; ``` <div class="ts-block-property-details"> A function that is called with the current route `config` and `prerender` option and returns an `App.Platform` object </div> </div></div> ## Handle The [`handle`](/docs/kit/hooks#Server-hooks-handle) hook runs every time the SvelteKit server receives a [request](/docs/kit/web-standards#Fetch-APIs-Request) and determines the [response](/docs/kit/web-standards#Fetch-APIs-Response). It receives an `event` object representing the request and a function called `resolve`, which renders the route and generates a `Response`. This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example). <div class="ts-block"> ```dts type Handle = (input: { event: RequestEvent; resolve: ( event: RequestEvent, opts?: ResolveOptions ) => MaybePromise<Response>; }) => MaybePromise<Response>; ``` </div> ## HandleClientError The client-side [`handleError`](/docs/kit/hooks#Shared-hooks-handleError) hook runs when an unexpected error is thrown while navigating. If an unexpected error is thrown during loading or the following render, this function will be called with the error and the event. Make sure that this function _never_ throws an error. <div class="ts-block"> ```dts type HandleClientError = (input: { error: unknown; event: NavigationEvent; status: number; message: string; }) => MaybePromise<void | App.Error>; ``` </div> ## HandleFetch The [`handleFetch`](/docs/kit/hooks#Server-hooks-handleFetch) hook allows you to modify (or replace) a `fetch` request that happens inside a `load` function that runs on the server (or during pre-rendering) <div class="ts-block"> ```dts type HandleFetch = (input: { event: RequestEvent; request: Request; fetch: typeof fetch; }) => MaybePromise<Response>; ``` </div> ## HandleServerError The server-side [`handleError`](/docs/kit/hooks#Shared-hooks-handleError) hook runs when an unexpected error is thrown while responding to a request. If an unexpected error is thrown during loading or rendering, this function will be called with the error and the event. Make sure that this function _never_ throws an error. <div class="ts-block"> ```dts type HandleServerError = (input: { error: unknown; event: RequestEvent; status: number; message: string; }) => MaybePromise<void | App.Error>; ``` </div> ## HttpError The object returned by the [`error`](/docs/kit/@sveltejs-kit#error) function. <div class="ts-block"> ```dts interface HttpError {/*…*/} ``` <div class="ts-block-property"> ```dts status: number; ``` <div class="ts-block-property-details"> The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses), in the range 400-599. </div> </div> <div class="ts-block-property"> ```dts body: App.Error; ``` <div class="ts-block-property-details"> The content of the error. </div> </div></div> ## KitConfig See the [configuration reference](/docs/kit/configuration) for details. ## LessThan <div class="ts-block"> ```dts type LessThan< TNumber extends number, TArray extends any[] = [] > = TNumber extends TArray['length'] ? TArray[number] : LessThan<TNumber, [...TArray, TArray['length']]>; ``` </div> ## Load The generic form of `PageLoad` and `LayoutLoad`. You should import those from `./$types` (see [generated types](/docs/kit/types#Generated-types)) rather than using `Load` directly. <div class="ts-block"> ```dts type Load< Params extends Partial<Record<string, string>> = Partial< Record<string, string> >, InputData extends Record<string, unknown> | null = Record< string, any > | null, ParentData extends Record<string, unknown> = Record< string, any >, OutputData extends Record< string, unknown > | void = Record<string, any> | void, RouteId extends string | null = string | null > = ( event: LoadEvent<Params, InputData, ParentData, RouteId> ) => MaybePromise<OutputData>; ``` </div> ## LoadEvent The generic form of `PageLoadEvent` and `LayoutLoadEvent`. You should import those from `./$types` (see [generated types](/docs/kit/types#Generated-types)) rather than using `LoadEvent` directly. <div class="ts-block"> ```dts interface LoadEvent< Params extends Partial<Record<string, string>> = Partial< Record<string, string> >, Data extends Record<string, unknown> | null = Record< string, any > | null, ParentData extends Record<string, unknown> = Record< string, any >, RouteId extends string | null = string | null > extends NavigationEvent<Params, RouteId> {/*…*/} ``` <div class="ts-block-property"> ```dts fetch: typeof fetch; ``` <div class="ts-block-property-details"> `fetch` is equivalent to the [native `fetch` web API](https://developer.mozilla.org/en-US/docs/Web/API/fetch), with a few additional features: - It can be used to make credentialed requests on the server, as it inherits the `cookie` and `authorization` headers for the page request. - It can make relative requests on the server (ordinarily, `fetch` requires a URL with an origin when used in a server context). - Internal requests (e.g. for `+server.js` routes) go directly to the handler function when running on the server, without the overhead of an HTTP call. - During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the `text` and `json` methods of the `Response` object. Note that headers will _not_ be serialized, unless explicitly included via [`filterSerializedResponseHeaders`](/docs/kit/hooks#Server-hooks-handle) - During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request. You can learn more about making credentialed requests with cookies [here](/docs/kit/load#Cookies) </div> </div> <div class="ts-block-property"> ```dts data: Data; ``` <div class="ts-block-property-details"> Contains the data returned by the route's server `load` function (in `+layout.server.js` or `+page.server.js`), if any. </div> </div> <div class="ts-block-property"> ```dts setHeaders: (headers: Record<string, string>) => void; ``` <div class="ts-block-property-details"> If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example: ```js // @errors: 7031 /// file: src/routes/blog/+page.js export async function load({ fetch, setHeaders }) { const url = `https://cms.example.com/articles.json`; const response = await fetch(url); setHeaders({ age: response.headers.get('age'), 'cache-control': response.headers.get('cache-control') }); return response.json(); } ``` Setting the same header multiple times (even in separate `load` functions) is an error — you can only set a given header once. You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](/docs/kit/@sveltejs-kit#Cookies) API in a server-only `load` function instead. `setHeaders` has no effect when a `load` function runs in the browser. </div> </div> <div class="ts-block-property"> ```dts parent: () => Promise<ParentData>; ``` <div class="ts-block-property-details"> `await parent()` returns data from parent `+layout.js` `load` functions. Implicitly, a missing `+layout.js` is treated as a `({ data }) => data` function, meaning that it will return and forward data from parent `+layout.server.js` files. Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data. </div> </div> <div class="ts-block-property"> ```dts depends: (...deps: Array<`${string}:${string}`>) => void; ``` <div class="ts-block-property-details"> This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](/docs/kit/$app-navigation#invalidate) to cause `load` to rerun. Most of the time you won't need this, as `fetch` calls `depends` on your behalf — it's only necessary if you're using a custom API client that bypasses `fetch`. URLs can be absolute or relative to the page being loaded, and must be [encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding). Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the [URI specification](https://www.rfc-editor.org/rfc/rfc3986.html). The following example shows how to use `depends` to register a dependency on a custom identifier, which is `invalidate`d after a button click, making the `load` function rerun. ```js // @errors: 7031 /// file: src/routes/+page.js let count = 0; export async function load({ depends }) { depends('increase:count'); return { count: count++ }; } ``` ```html /// file: src/routes/+page.svelte <script> import { invalidate } from '$app/navigation'; let { data } = $props(); const increase = async () => { await invalidate('increase:count'); } </script> <p>{data.count}<p> <button on:click={increase}>Increase Count</button> ``` </div> </div> <div class="ts-block-property"> ```dts untrack: <T>(fn: () => T) => T; ``` <div class="ts-block-property-details"> Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example: ```js // @errors: 7031 /// file: src/routes/+page.server.js export async function load({ untrack, url }) { // Untrack url.pathname so that path changes don't trigger a rerun if (untrack(() => url.pathname === '/')) { return { message: 'Welcome!' }; } } ``` </div> </div></div> ## LoadProperties <div class="ts-block"> ```dts type LoadProperties< input extends Record<string, any> | void > = input extends void ? undefined // needs to be undefined, because void will break intellisense : input extends Record<string, any> ? input : unknown; ``` </div> ## Navigation <div class="ts-block"> ```dts interface Navigation {/*…*/} ``` <div class="ts-block-property"> ```dts from: NavigationTarget | null; ``` <div class="ts-block-property-details"> Where navigation was triggered from </div> </div> <div class="ts-block-property"> ```dts to: NavigationTarget | null; ``` <div class="ts-block-property-details"> Where navigation is going to/has gone to </div> </div> <div class="ts-block-property"> ```dts type: Exclude<NavigationType, 'enter'>; ``` <div class="ts-block-property-details"> The type of navigation: - `form`: The user submitted a `<form>` - `leave`: The app is being left either because the tab is being closed or a navigation to a different document is occurring - `link`: Navigation was triggered by a link click - `goto`: Navigation was triggered by a `goto(...)` call or a redirect - `popstate`: Navigation was triggered by back/forward navigation </div> </div> <div class="ts-block-property"> ```dts willUnload: boolean; ``` <div class="ts-block-property-details"> Whether or not the navigation will result in the page being unloaded (i.e. not a client-side navigation) </div> </div> <div class="ts-block-property"> ```dts delta?: number; ``` <div class="ts-block-property-details"> In case of a history back/forward navigation, the number of steps to go back/forward </div> </div> <div class="ts-block-property"> ```dts complete: Promise<void>; ``` <div class="ts-block-property-details"> A promise that resolves once the navigation is complete, and rejects if the navigation fails or is aborted. In the case of a `willUnload` navigation, the promise will never resolve </div> </div></div> ## NavigationEvent <div class="ts-block"> ```dts interface NavigationEvent< Params extends Partial<Record<string, string>> = Partial< Record<string, string> >, RouteId extends string | null = string | null > {/*…*/} ``` <div class="ts-block-property"> ```dts params: Params; ``` <div class="ts-block-property-details"> The parameters of the current page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object </div> </div> <div class="ts-block-property"> ```dts route: {/*…*/} ``` <div class="ts-block-property-details"> Info about the current route <div class="ts-block-property-children"><div class="ts-block-property"> ```dts id: RouteId; ``` <div class="ts-block-property-details"> The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]` </div> </div></div> </div> </div> <div class="ts-block-property"> ```dts url: URL; ``` <div class="ts-block-property-details"> The URL of the current page </div> </div></div> ## NavigationTarget Information about the target of a specific navigation. <div class="ts-block"> ```dts interface NavigationTarget {/*…*/} ``` <div class="ts-block-property"> ```dts params: Record<string, string> | null; ``` <div class="ts-block-property-details"> Parameters of the target page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object. Is `null` if the target is not part of the SvelteKit app (could not be resolved to a route). </div> </div> <div class="ts-block-property"> ```dts route: { id: string | null }; ``` <div class="ts-block-property-details"> Info about the target route </div> </div> <div class="ts-block-property"> ```dts url: URL; ``` <div class="ts-block-property-details"> The URL that is navigated to </div> </div></div> ## NavigationType - `enter`: The app has hydrated - `form`: The user submitted a `<form>` with a GET method - `leave`: The user is leaving the app by closing the tab or using the back/forward buttons to go to a different document - `link`: Navigation was triggered by a link click - `goto`: Navigation was triggered by a `goto(...)` call or a redirect - `popstate`: Navigation was triggered by back/forward navigation <div class="ts-block"> ```dts type NavigationType = | 'enter' | 'form' | 'leave' | 'link' | 'goto' | 'popstate'; ``` </div> ## NumericRange <div class="ts-block"> ```dts type NumericRange< TStart extends number, TEnd extends number > = Exclude<TEnd | LessThan<TEnd>, LessThan<TStart>>; ``` </div> ## OnNavigate The argument passed to [`onNavigate`](/docs/kit/$app-navigation#onNavigate) callbacks. <div class="ts-block"> ```dts interface OnNavigate extends Navigation {/*…*/} ``` <div class="ts-block-property"> ```dts type: Exclude<NavigationType, 'enter' | 'leave'>; ``` <div class="ts-block-property-details"> The type of navigation: - `form`: The user submitted a `<form>` - `link`: Navigation was triggered by a link click - `goto`: Navigation was triggered by a `goto(...)` call or a redirect - `popstate`: Navigation was triggered by back/forward navigation </div> </div> <div class="ts-block-property"> ```dts willUnload: false; ``` <div class="ts-block-property-details"> Since `onNavigate` callbacks are called immediately before a client-side navigation, they will never be called with a navigation that unloads the page. </div> </div></div> ## Page The shape of the [`page`](/docs/kit/$app-state#page) reactive object and the [`$page`](/docs/kit/$app-stores) store. <div class="ts-block"> ```dts interface Page< Params extends Record<string, string> = Record< string, string >, RouteId extends string | null = string | null > {/*…*/} ``` <div class="ts-block-property"> ```dts url: URL; ``` <div class="ts-block-property-details"> The URL of the current page. </div> </div> <div class="ts-block-property"> ```dts params: Params; ``` <div class="ts-block-property-details"> The parameters of the current page - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object. </div> </div> <div class="ts-block-property"> ```dts route: {/*…*/} ``` <div class="ts-block-property-details"> Info about the current route. <div class="ts-block-property-children"><div class="ts-block-property"> ```dts id: RouteId; ``` <div class="ts-block-property-details"> The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. </div> </div></div> </div> </div> <div class="ts-block-property"> ```dts status: number; ``` <div class="ts-block-property-details"> HTTP status code of the current page. </div> </div> <div class="ts-block-property"> ```dts error: App.Error | null; ``` <div class="ts-block-property-details"> The error object of the current page, if any. Filled from the `handleError` hooks. </div> </div> <div class="ts-block-property"> ```dts data: App.PageData & Record<string, any>; ``` <div class="ts-block-property-details"> The merged result of all data from all `load` functions on the current page. You can type a common denominator through `App.PageData`. </div> </div> <div class="ts-block-property"> ```dts state: App.PageState; ``` <div class="ts-block-property-details"> The page state, which can be manipulated using the [`pushState`](/docs/kit/$app-navigation#pushState) and [`replaceState`](/docs/kit/$app-navigation#replaceState) functions from `$app/navigation`. </div> </div> <div class="ts-block-property"> ```dts form: any; ``` <div class="ts-block-property-details"> Filled only after a form submission. See [form actions](/docs/kit/form-actions) for more info. </div> </div></div> ## ParamMatcher The shape of a param matcher. See [matching](/docs/kit/advanced-routing#Matching) for more info. <div class="ts-block"> ```dts type ParamMatcher = (param: string) => boolean; ``` </div> ## PrerenderOption <div class="ts-block"> ```dts type PrerenderOption = boolean | 'auto'; ``` </div> ## Redirect The object returned by the [`redirect`](/docs/kit/@sveltejs-kit#redirect) function. <div class="ts-block"> ```dts interface Redirect {/*…*/} ``` <div class="ts-block-property"> ```dts status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308; ``` <div class="ts-block-property-details"> The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#redirection_messages), in the range 300-308. </div> </div> <div class="ts-block-property"> ```dts location: string; ``` <div class="ts-block-property-details"> The location to redirect to. </div> </div></div> ## RequestEvent <div class="ts-block"> ```dts interface RequestEvent< Params extends Partial<Record<string, string>> = Partial< Record<string, string> >, RouteId extends string | null = string | null > {/*…*/} ``` <div class="ts-block-property"> ```dts cookies: Cookies; ``` <div class="ts-block-property-details"> Get or set cookies related to the current request </div> </div> <div class="ts-block-property"> ```dts fetch: typeof fetch; ``` <div class="ts-block-property-details"> `fetch` is equivalent to the [native `fetch` web API](https://developer.mozilla.org/en-US/docs/Web/API/fetch), with a few additional features: - It can be used to make credentialed requests on the server, as it inherits the `cookie` and `authorization` headers for the page request. - It can make relative requests on the server (ordinarily, `fetch` requires a URL with an origin when used in a server context). - Internal requests (e.g. for `+server.js` routes) go directly to the handler function when running on the server, without the overhead of an HTTP call. - During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the `text` and `json` methods of the `Response` object. Note that headers will _not_ be serialized, unless explicitly included via [`filterSerializedResponseHeaders`](/docs/kit/hooks#Server-hooks-handle) - During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request. You can learn more about making credentialed requests with cookies [here](/docs/kit/load#Cookies). </div> </div> <div class="ts-block-property"> ```dts getClientAddress: () => string; ``` <div class="ts-block-property-details"> The client's IP address, set by the adapter. </div> </div> <div class="ts-block-property"> ```dts locals: App.Locals; ``` <div class="ts-block-property-details"> Contains custom data that was added to the request within the [`server handle hook`](/docs/kit/hooks#Server-hooks-handle). </div> </div> <div class="ts-block-property"> ```dts params: Params; ``` <div class="ts-block-property-details"> The parameters of the current route - e.g. for a route like `/blog/[slug]`, a `{ slug: string }` object. </div> </div> <div class="ts-block-property"> ```dts platform: Readonly<App.Platform> | undefined; ``` <div class="ts-block-property-details"> Additional data made available through the adapter. </div> </div> <div class="ts-block-property"> ```dts request: Request; ``` <div class="ts-block-property-details"> The original request object. </div> </div> <div class="ts-block-property"> ```dts route: {/*…*/} ``` <div class="ts-block-property-details"> Info about the current route. <div class="ts-block-property-children"><div class="ts-block-property"> ```dts id: RouteId; ``` <div class="ts-block-property-details"> The ID of the current route - e.g. for `src/routes/blog/[slug]`, it would be `/blog/[slug]`. </div> </div></div> </div> </div> <div class="ts-block-property"> ```dts setHeaders: (headers: Record<string, string>) => void; ``` <div class="ts-block-property-details"> If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example: ```js // @errors: 7031 /// file: src/routes/blog/+page.js export async function load({ fetch, setHeaders }) { const url = `https://cms.example.com/articles.json`; const response = await fetch(url); setHeaders({ age: response.headers.get('age'), 'cache-control': response.headers.get('cache-control') }); return response.json(); } ``` Setting the same header multiple times (even in separate `load` functions) is an error — you can only set a given header once. You cannot add a `set-cookie` header with `setHeaders` — use the [`cookies`](/docs/kit/@sveltejs-kit#Cookies) API instead. </div> </div> <div class="ts-block-property"> ```dts url: URL; ``` <div class="ts-block-property-details"> The requested URL. </div> </div> <div class="ts-block-property"> ```dts isDataRequest: boolean; ``` <div class="ts-block-property-details"> `true` if the request comes from the client asking for `+page/layout.server.js` data. The `url` property will be stripped of the internal information related to the data request in this case. Use this property instead if the distinction is important to you. </div> </div> <div class="ts-block-property"> ```dts isSubRequest: boolean; ``` <div class="ts-block-property-details"> `true` for `+server.js` calls coming from SvelteKit without the overhead of actually making an HTTP request. This happens when you make same-origin `fetch` requests on the server. </div> </div></div> ## RequestHandler A `(event: RequestEvent) => Response` function exported from a `+server.js` file that corresponds to an HTTP verb (`GET`, `PUT`, `PATCH`, etc) and handles requests with that method. It receives `Params` as the first generic argument, which you can skip by using [generated types](/docs/kit/types#Generated-types) instead. <div class="ts-block"> ```dts type RequestHandler< Params extends Partial<Record<string, string>> = Partial< Record<string, string> >, RouteId extends string | null = string | null > = ( event: RequestEvent<Params, RouteId> ) => MaybePromise<Response>; ``` </div> ## Reroute <blockquote class="since note"> Available since 2.3.0 </blockquote> The [`reroute`](/docs/kit/hooks#Universal-hooks-reroute) hook allows you to modify the URL before it is used to determine which route to render. <div class="ts-block"> ```dts type Reroute = (event: { url: URL; }) => MaybePromise<void | string>; ``` </div> ## ResolveOptions <div class="ts-block"> ```dts interface ResolveOptions {/*…*/} ``` <div class="ts-block-property"> ```dts transformPageChunk?: (input: { html: string; done: boolean }) => MaybePromise<string | undefined>; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `input` the html chunk and the info if this is the last chunk </div> Applies custom transforms to HTML. If `done` is true, it's the final chunk. Chunks are not guaranteed to be well-formed HTML (they could include an element's opening tag but not its closing tag, for example) but they will always be split at sensible boundaries such as `%sveltekit.head%` or layout/page components. </div> </div> <div class="ts-block-property"> ```dts filterSerializedResponseHeaders?: (name: string, value: string) => boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `name` header name - `value` header value </div> Determines which headers should be included in serialized responses when a `load` function loads a resource with `fetch`. By default, none will be included. </div> </div> <div class="ts-block-property"> ```dts preload?: (input: { type: 'font' | 'css' | 'js' | 'asset'; path: string }) => boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - `input` the type of the file and its path </div> Determines what should be added to the `<head>` tag to preload it. By default, `js` and `css` files will be preloaded. </div> </div></div> ## RouteDefinition <div class="ts-block"> ```dts interface RouteDefinition<Config = any> {/*…*/} ``` <div class="ts-block-property"> ```dts id: string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts api: { methods: Array<HttpMethod | '*'>; }; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts page: { methods: Array<Extract<HttpMethod, 'GET' | 'POST'>>; }; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts pattern: RegExp; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts prerender: PrerenderOption; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts segments: RouteSegment[]; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts methods: Array<HttpMethod | '*'>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts config: Config; ``` <div class="ts-block-property-details"></div> </div></div> ## SSRManifest <div class="ts-block"> ```dts interface SSRManifest {/*…*/} ``` <div class="ts-block-property"> ```dts appDir: string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts appPath: string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts assets: Set<string>; ``` <div class="ts-block-property-details"> Static files from `kit.config.files.assets` and the service worker (if any). </div> </div> <div class="ts-block-property"> ```dts mimeTypes: Record<string, string>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts _: {/*…*/} ``` <div class="ts-block-property-details"> private fields <div class="ts-block-property-children"><div class="ts-block-property"> ```dts client: NonNullable<BuildData['client']>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts nodes: SSRNodeLoader[]; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts routes: SSRRoute[]; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts prerendered_routes: Set<string>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts matchers: () => Promise<Record<string, ParamMatcher>>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts server_assets: Record<string, number>; ``` <div class="ts-block-property-details"> A `[file]: size` map of all assets imported by server code. </div> </div></div> </div> </div></div> ## ServerInit <blockquote class="since note"> Available since 2.10.0 </blockquote> The [`init`](/docs/kit/hooks#Shared-hooks-init) will be invoked before the server responds to its first request <div class="ts-block"> ```dts type ServerInit = () => MaybePromise<void>; ``` </div> ## ServerInitOptions <div class="ts-block"> ```dts interface ServerInitOptions {/*…*/} ``` <div class="ts-block-property"> ```dts env: Record<string, string>; ``` <div class="ts-block-property-details"> A map of environment variables. </div> </div> <div class="ts-block-property"> ```dts read?: (file: string) => ReadableStream; ``` <div class="ts-block-property-details"> A function that turns an asset filename into a `ReadableStream`. Required for the `read` export from `$app/server` to work. </div> </div></div> ## ServerLoad The generic form of `PageServerLoad` and `LayoutServerLoad`. You should import those from `./$types` (see [generated types](/docs/kit/types#Generated-types)) rather than using `ServerLoad` directly. <div class="ts-block"> ```dts type ServerLoad< Params extends Partial<Record<string, string>> = Partial< Record<string, string> >, ParentData extends Record<string, any> = Record< string, any >, OutputData extends Record<string, any> | void = Record< string, any > | void, RouteId extends string | null = string | null > = ( event: ServerLoadEvent<Params, ParentData, RouteId> ) => MaybePromise<OutputData>; ``` </div> ## ServerLoadEvent <div class="ts-block"> ```dts interface ServerLoadEvent< Params extends Partial<Record<string, string>> = Partial< Record<string, string> >, ParentData extends Record<string, any> = Record< string, any >, RouteId extends string | null = string | null > extends RequestEvent<Params, RouteId> {/*…*/} ``` <div class="ts-block-property"> ```dts parent: () => Promise<ParentData>; ``` <div class="ts-block-property-details"> `await parent()` returns data from parent `+layout.server.js` `load` functions. Be careful not to introduce accidental waterfalls when using `await parent()`. If for example you only want to merge parent data into the returned output, call it _after_ fetching your other data. </div> </div> <div class="ts-block-property"> ```dts depends: (...deps: string[]) => void; ``` <div class="ts-block-property-details"> This function declares that the `load` function has a _dependency_ on one or more URLs or custom identifiers, which can subsequently be used with [`invalidate()`](/docs/kit/$app-navigation#invalidate) to cause `load` to rerun. Most of the time you won't need this, as `fetch` calls `depends` on your behalf — it's only necessary if you're using a custom API client that bypasses `fetch`. URLs can be absolute or relative to the page being loaded, and must be [encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding). Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the [URI specification](https://www.rfc-editor.org/rfc/rfc3986.html). The following example shows how to use `depends` to register a dependency on a custom identifier, which is `invalidate`d after a button click, making the `load` function rerun. ```js // @errors: 7031 /// file: src/routes/+page.js let count = 0; export async function load({ depends }) { depends('increase:count'); return { count: count++ }; } ``` ```html /// file: src/routes/+page.svelte <script> import { invalidate } from '$app/navigation'; let { data } = $props(); const increase = async () => { await invalidate('increase:count'); } </script> <p>{data.count}<p> <button on:click={increase}>Increase Count</button> ``` </div> </div> <div class="ts-block-property"> ```dts untrack: <T>(fn: () => T) => T; ``` <div class="ts-block-property-details"> Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example: ```js // @errors: 7031 /// file: src/routes/+page.js export async function load({ untrack, url }) { // Untrack url.pathname so that path changes don't trigger a rerun if (untrack(() => url.pathname === '/')) { return { message: 'Welcome!' }; } } ``` </div> </div></div> ## Snapshot The type of `export const snapshot` exported from a page or layout component. <div class="ts-block"> ```dts interface Snapshot<T = any> {/*…*/} ``` <div class="ts-block-property"> ```dts capture: () => T; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts restore: (snapshot: T) => void; ``` <div class="ts-block-property-details"></div> </div></div> ## SubmitFunction <div class="ts-block"> ```dts type SubmitFunction< Success extends | Record<string, unknown> | undefined = Record<string, any>, Failure extends | Record<string, unknown> | undefined = Record<string, any> > = (input: { action: URL; formData: FormData; formElement: HTMLFormElement; controller: AbortController; submitter: HTMLElement | null; cancel: () => void; }) => MaybePromise< | void | ((opts: { formData: FormData; formElement: HTMLFormElement; action: URL; result: ActionResult<Success, Failure>; /** * Call this to get the default behavior of a form submission response. * @param options Set `reset: false` if you don't want the `<form>` values to be reset after a successful submission. * @param invalidateAll Set `invalidateAll: false` if you don't want the action to call `invalidateAll` after submission. */ update: (options?: { reset?: boolean; invalidateAll?: boolean; }) => Promise<void>; }) => MaybePromise<void>) >; ``` </div> ## Transport <blockquote class="since note"> Available since 2.11.0 </blockquote> The [`transport`](/docs/kit/hooks#Universal-hooks-transport) hook allows you to transport custom types across the server/client boundary. Each transporter has a pair of `encode` and `decode` functions. On the server, `encode` determines whether a value is an instance of the custom type and, if so, returns a non-falsy encoding of the value which can be an object or an array (or `false` otherwise). In the browser, `decode` turns the encoding back into an instance of the custom type. ```ts import type { Transport } from '@sveltejs/kit'; declare class MyCustomType { data: any } // hooks.js export const transport: Transport = { MyCustomType: { encode: (value) => value instanceof MyCustomType && [value.data], decode: ([data]) => new MyCustomType(data) } }; ``` <div class="ts-block"> ```dts type Transport = Record<string, Transporter>; ``` </div> ## Transporter A member of the [`transport`](/docs/kit/hooks#Universal-hooks-transport) hook. <div class="ts-block"> ```dts interface Transporter< T = any, U = Exclude< any, false | 0 | '' | null | undefined | typeof NaN > > {/*…*/} ``` <div class="ts-block-property"> ```dts encode: (value: T) => false | U; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts decode: (data: U) => T; ``` <div class="ts-block-property-details"></div> </div></div> ## Private types The following are referenced by the public types documented above, but cannot be imported directly: ## AdapterEntry <div class="ts-block"> ```dts interface AdapterEntry {/*…*/} ``` <div class="ts-block-property"> ```dts id: string; ``` <div class="ts-block-property-details"> A string that uniquely identifies an HTTP service (e.g. serverless function) and is used for deduplication. For example, `/foo/a-[b]` and `/foo/[c]` are different routes, but would both be represented in a Netlify _redirects file as `/foo/:param`, so they share an ID </div> </div> <div class="ts-block-property"> ```dts filter(route: RouteDefinition): boolean; ``` <div class="ts-block-property-details"> A function that compares the candidate route with the current route to determine if it should be grouped with the current route. Use cases: - Fallback pages: `/foo/[c]` is a fallback for `/foo/a-[b]`, and `/[...catchall]` is a fallback for all routes - Grouping routes that share a common `config`: `/foo` should be deployed to the edge, `/bar` and `/baz` should be deployed to a serverless function </div> </div> <div class="ts-block-property"> ```dts complete(entry: { generateManifest(opts: { relativePath: string }): string }): MaybePromise<void>; ``` <div class="ts-block-property-details"> A function that is invoked once the entry has been created. This is where you should write the function to the filesystem and generate redirect manifests. </div> </div></div> ## Csp <div class="ts-block"> ```dts namespace Csp { type ActionSource = 'strict-dynamic' | 'report-sample'; type BaseSource = | 'self' | 'unsafe-eval' | 'unsafe-hashes' | 'unsafe-inline' | 'wasm-unsafe-eval' | 'none'; type CryptoSource = `${'nonce' | 'sha256' | 'sha384' | 'sha512'}-${string}`; type FrameSource = | HostSource | SchemeSource | 'self' | 'none'; type HostNameScheme = `${string}.${string}` | 'localhost'; type HostSource = `${HostProtocolSchemes}${HostNameScheme}${PortScheme}`; type HostProtocolSchemes = `${string}://` | ''; type HttpDelineator = '/' | '?' | '#' | '\\'; type PortScheme = `:${number}` | '' | ':*'; type SchemeSource = | 'http:' | 'https:' | 'data:' | 'mediastream:' | 'blob:' | 'filesystem:'; type Source = | HostSource | SchemeSource | CryptoSource | BaseSource; type Sources = Source[]; } ``` </div> ## CspDirectives <div class="ts-block"> ```dts interface CspDirectives {/*…*/} ``` <div class="ts-block-property"> ```dts 'child-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'default-src'?: Array<Csp.Source | Csp.ActionSource>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'frame-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'worker-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'connect-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'font-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'img-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'manifest-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'media-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'object-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'prefetch-src'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'script-src'?: Array<Csp.Source | Csp.ActionSource>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'script-src-elem'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'script-src-attr'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'style-src'?: Array<Csp.Source | Csp.ActionSource>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'style-src-elem'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'style-src-attr'?: Csp.Sources; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'base-uri'?: Array<Csp.Source | Csp.ActionSource>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts sandbox?: Array< | 'allow-downloads-without-user-activation' | 'allow-forms' | 'allow-modals' | 'allow-orientation-lock' | 'allow-pointer-lock' | 'allow-popups' | 'allow-popups-to-escape-sandbox' | 'allow-presentation' | 'allow-same-origin' | 'allow-scripts' | 'allow-storage-access-by-user-activation' | 'allow-top-navigation' | 'allow-top-navigation-by-user-activation' >; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'form-action'?: Array<Csp.Source | Csp.ActionSource>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'frame-ancestors'?: Array<Csp.HostSource | Csp.SchemeSource | Csp.FrameSource>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'navigate-to'?: Array<Csp.Source | Csp.ActionSource>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'report-uri'?: string[]; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'report-to'?: string[]; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'require-trusted-types-for'?: Array<'script'>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'trusted-types'?: Array<'none' | 'allow-duplicates' | '*' | string>; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'upgrade-insecure-requests'?: boolean; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts 'require-sri-for'?: Array<'script' | 'style' | 'script style'>; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> </div> </div> </div> <div class="ts-block-property"> ```dts 'block-all-mixed-content'?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> </div> </div> </div> <div class="ts-block-property"> ```dts 'plugin-types'?: Array<`${string}/${string}` | 'none'>; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> </div> </div> </div> <div class="ts-block-property"> ```dts referrer?: Array< | 'no-referrer' | 'no-referrer-when-downgrade' | 'origin' | 'origin-when-cross-origin' | 'same-origin' | 'strict-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url' | 'none' >; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag deprecated">deprecated</span> </div> </div> </div></div> ## HttpMethod <div class="ts-block"> ```dts type HttpMethod = | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS'; ``` </div> ## Logger <div class="ts-block"> ```dts interface Logger {/*…*/} ``` <div class="ts-block-property"> ```dts (msg: string): void; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts success(msg: string): void; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts error(msg: string): void; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts warn(msg: string): void; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts minor(msg: string): void; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts info(msg: string): void; ``` <div class="ts-block-property-details"></div> </div></div> ## MaybePromise <div class="ts-block"> ```dts type MaybePromise<T> = T | Promise<T>; ``` </div> ## PrerenderEntryGeneratorMismatchHandler <div class="ts-block"> ```dts interface PrerenderEntryGeneratorMismatchHandler {/*…*/} ``` <div class="ts-block-property"> ```dts (details: { generatedFromId: string; entry: string; matchedId: string; message: string }): void; ``` <div class="ts-block-property-details"></div> </div></div> ## PrerenderEntryGeneratorMismatchHandlerValue <div class="ts-block"> ```dts type PrerenderEntryGeneratorMismatchHandlerValue = | 'fail' | 'warn' | 'ignore' | PrerenderEntryGeneratorMismatchHandler; ``` </div> ## PrerenderHttpErrorHandler <div class="ts-block"> ```dts interface PrerenderHttpErrorHandler {/*…*/} ``` <div class="ts-block-property"> ```dts (details: { status: number; path: string; referrer: string | null; referenceType: 'linked' | 'fetched'; message: string; }): void; ``` <div class="ts-block-property-details"></div> </div></div> ## PrerenderHttpErrorHandlerValue <div class="ts-block"> ```dts type PrerenderHttpErrorHandlerValue = | 'fail' | 'warn' | 'ignore' | PrerenderHttpErrorHandler; ``` </div> ## PrerenderMap <div class="ts-block"> ```dts type PrerenderMap = Map<string, PrerenderOption>; ``` </div> ## PrerenderMissingIdHandler <div class="ts-block"> ```dts interface PrerenderMissingIdHandler {/*…*/} ``` <div class="ts-block-property"> ```dts (details: { path: string; id: string; referrers: string[]; message: string }): void; ``` <div class="ts-block-property-details"></div> </div></div> ## PrerenderMissingIdHandlerValue <div class="ts-block"> ```dts type PrerenderMissingIdHandlerValue = | 'fail' | 'warn' | 'ignore' | PrerenderMissingIdHandler; ``` </div> ## PrerenderOption <div class="ts-block"> ```dts type PrerenderOption = boolean | 'auto'; ``` </div> ## Prerendered <div class="ts-block"> ```dts interface Prerendered {/*…*/} ``` <div class="ts-block-property"> ```dts pages: Map< string, { /** The location of the .html file relative to the output directory */ file: string; } >; ``` <div class="ts-block-property-details"> A map of `path` to `{ file }` objects, where a path like `/foo` corresponds to `foo.html` and a path like `/bar/` corresponds to `bar/index.html`. </div> </div> <div class="ts-block-property"> ```dts assets: Map< string, { /** The MIME type of the asset */ type: string; } >; ``` <div class="ts-block-property-details"> A map of `path` to `{ type }` objects. </div> </div> <div class="ts-block-property"> ```dts redirects: Map< string, { status: number; location: string; } >; ``` <div class="ts-block-property-details"> A map of redirects encountered during prerendering. </div> </div> <div class="ts-block-property"> ```dts paths: string[]; ``` <div class="ts-block-property-details"> An array of prerendered paths (without trailing slashes, regardless of the trailingSlash config) </div> </div></div> ## RequestOptions <div class="ts-block"> ```dts interface RequestOptions {/*…*/} ``` <div class="ts-block-property"> ```dts getClientAddress(): string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts platform?: App.Platform; ``` <div class="ts-block-property-details"></div> </div></div> ## RouteSegment <div class="ts-block"> ```dts interface RouteSegment {/*…*/} ``` <div class="ts-block-property"> ```dts content: string; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts dynamic: boolean; ``` <div class="ts-block-property-details"></div> </div> <div class="ts-block-property"> ```dts rest: boolean; ``` <div class="ts-block-property-details"></div> </div></div> ## TrailingSlash <div class="ts-block"> ```dts type TrailingSlash = 'never' | 'always' | 'ignore'; ``` </div>

# @sveltejs/kit/hooks

```js // @noErrors import { sequence } from '@sveltejs/kit/hooks'; ``` ## sequence A helper function for sequencing multiple `handle` calls in a middleware-like manner. The behavior for the `handle` options is as follows: - `transformPageChunk` is applied in reverse order and merged - `preload` is applied in forward order, the first option "wins" and no `preload` options after it are called - `filterSerializedResponseHeaders` behaves the same as `preload` ```js // @errors: 7031 /// file: src/hooks.server.js import { sequence } from '@sveltejs/kit/hooks'; /** @type {import('@sveltejs/kit').Handle} */ async function first({ event, resolve }) { console.log('first pre-processing'); const result = await resolve(event, { transformPageChunk: ({ html }) => { // transforms are applied in reverse order console.log('first transform'); return html; }, preload: () => { // this one wins as it's the first defined in the chain console.log('first preload'); return true; } }); console.log('first post-processing'); return result; } /** @type {import('@sveltejs/kit').Handle} */ async function second({ event, resolve }) { console.log('second pre-processing'); const result = await resolve(event, { transformPageChunk: ({ html }) => { console.log('second transform'); return html; }, preload: () => { console.log('second preload'); return true; }, filterSerializedResponseHeaders: () => { // this one wins as it's the first defined in the chain console.log('second filterSerializedResponseHeaders'); return true; } }); console.log('second post-processing'); return result; } export const handle = sequence(first, second); ``` The example above would print: ``` first pre-processing first preload second pre-processing second filterSerializedResponseHeaders second transform first transform second post-processing first post-processing ``` <div class="ts-block"> ```dts function sequence( ...handlers: import('@sveltejs/kit').Handle[] ): import('@sveltejs/kit').Handle; ``` </div>

# @sveltejs/kit/node/polyfills

```js // @noErrors import { installPolyfills } from '@sveltejs/kit/node/polyfills'; ``` ## installPolyfills Make various web APIs available as globals: - `crypto` - `File` <div class="ts-block"> ```dts function installPolyfills(): void; ``` </div>

# @sveltejs/kit/node

```js // @noErrors import { createReadableStream, getRequest, setResponse } from '@sveltejs/kit/node'; ``` ## createReadableStream <blockquote class="since note"> Available since 2.4.0 </blockquote> Converts a file on disk to a readable stream <div class="ts-block"> ```dts function createReadableStream(file: string): ReadableStream; ``` </div> ## getRequest <div class="ts-block"> ```dts function getRequest({ request, base, bodySizeLimit }: { request: import('http').IncomingMessage; base: string; bodySizeLimit?: number; }): Promise<Request>; ``` </div> ## setResponse <div class="ts-block"> ```dts function setResponse( res: import('http').ServerResponse, response: Response ): Promise<void>; ``` </div>

# @sveltejs/kit/vite

```js // @noErrors import { sveltekit } from '@sveltejs/kit/vite'; ``` ## sveltekit Returns the SvelteKit Vite plugins. <div class="ts-block"> ```dts function sveltekit(): Promise<import('vite').Plugin[]>; ``` </div>

# $app/environment

```js // @noErrors import { browser, building, dev, version } from '$app/environment'; ``` ## browser `true` if the app is running in the browser. <div class="ts-block"> ```dts const browser: boolean; ``` </div> ## building SvelteKit analyses your app during the `build` step by running it. During this process, `building` is `true`. This also applies during prerendering. <div class="ts-block"> ```dts const building: boolean; ``` </div> ## dev Whether the dev server is running. This is not guaranteed to correspond to `NODE_ENV` or `MODE`. <div class="ts-block"> ```dts const dev: boolean; ``` </div> ## version The value of `config.kit.version.name`. <div class="ts-block"> ```dts const version: string; ``` </div>

# $app/forms

```js // @noErrors import { applyAction, deserialize, enhance } from '$app/forms'; ``` ## applyAction This action updates the `form` property of the current page with the given data and updates `page.status`. In case of an error, it redirects to the nearest error page. <div class="ts-block"> ```dts function applyAction< Success extends Record<string, unknown> | undefined, Failure extends Record<string, unknown> | undefined >( result: import('@sveltejs/kit').ActionResult< Success, Failure > ): Promise<void>; ``` </div> ## deserialize Use this function to deserialize the response from a form submission. Usage: ```js // @errors: 7031 import { deserialize } from '$app/forms'; async function handleSubmit(event) { const response = await fetch('/form?/action', { method: 'POST', body: new FormData(event.target) }); const result = deserialize(await response.text()); // ... } ``` <div class="ts-block"> ```dts function deserialize< Success extends Record<string, unknown> | undefined, Failure extends Record<string, unknown> | undefined >( result: string ): import('@sveltejs/kit').ActionResult<Success, Failure>; ``` </div> ## enhance This action enhances a `<form>` element that otherwise would work without JavaScript. The `submit` function is called upon submission with the given FormData and the `action` that should be triggered. If `cancel` is called, the form will not be submitted. You can use the abort `controller` to cancel the submission in case another one starts. If a function is returned, that function is called with the response from the server. If nothing is returned, the fallback will be used. If this function or its return value isn't set, it - falls back to updating the `form` prop with the returned data if the action is on the same page as the form - updates `page.status` - resets the `<form>` element and invalidates all data in case of successful submission with no redirect response - redirects in case of a redirect response - redirects to the nearest error page in case of an unexpected error If you provide a custom function with a callback and want to use the default behavior, invoke `update` in your callback. It accepts an options object - `reset: false` if you don't want the `<form>` values to be reset after a successful submission - `invalidateAll: false` if you don't want the action to call `invalidateAll` after submission <div class="ts-block"> ```dts function enhance< Success extends Record<string, unknown> | undefined, Failure extends Record<string, unknown> | undefined >( form_element: HTMLFormElement, submit?: import('@sveltejs/kit').SubmitFunction< Success, Failure > ): { destroy(): void; }; ``` </div>

# $app/navigation

```js // @noErrors import { afterNavigate, beforeNavigate, disableScrollHandling, goto, invalidate, invalidateAll, onNavigate, preloadCode, preloadData, pushState, replaceState } from '$app/navigation'; ``` ## afterNavigate A lifecycle function that runs the supplied `callback` when the current component mounts, and also whenever we navigate to a URL. `afterNavigate` must be called during a component initialization. It remains active as long as the component is mounted. <div class="ts-block"> ```dts function afterNavigate( callback: ( navigation: import('@sveltejs/kit').AfterNavigate ) => void ): void; ``` </div> ## beforeNavigate A navigation interceptor that triggers before we navigate to a URL, whether by clicking a link, calling `goto(...)`, or using the browser back/forward controls. Calling `cancel()` will prevent the navigation from completing. If `navigation.type === 'leave'` — meaning the user is navigating away from the app (or closing the tab) — calling `cancel` will trigger the native browser unload confirmation dialog. In this case, the navigation may or may not be cancelled depending on the user's response. When a navigation isn't to a SvelteKit-owned route (and therefore controlled by SvelteKit's client-side router), `navigation.to.route.id` will be `null`. If the navigation will (if not cancelled) cause the document to unload — in other words `'leave'` navigations and `'link'` navigations where `navigation.to.route === null` — `navigation.willUnload` is `true`. `beforeNavigate` must be called during a component initialization. It remains active as long as the component is mounted. <div class="ts-block"> ```dts function beforeNavigate( callback: ( navigation: import('@sveltejs/kit').BeforeNavigate ) => void ): void; ``` </div> ## disableScrollHandling If called when the page is being updated following a navigation (in `onMount` or `afterNavigate` or an action, for example), this disables SvelteKit's built-in scroll handling. This is generally discouraged, since it breaks user expectations. <div class="ts-block"> ```dts function disableScrollHandling(): void; ``` </div> ## goto Allows you to navigate programmatically to a given route, with options such as keeping the current element focused. Returns a Promise that resolves when SvelteKit navigates (or fails to navigate, in which case the promise rejects) to the specified `url`. For external URLs, use `window.location = url` instead of calling `goto(url)`. <div class="ts-block"> ```dts function goto( url: string | URL, opts?: | { replaceState?: boolean | undefined; noScroll?: boolean | undefined; keepFocus?: boolean | undefined; invalidateAll?: boolean | undefined; invalidate?: | (string | URL | ((url: URL) => boolean))[] | undefined; state?: App.PageState | undefined; } | undefined ): Promise<void>; ``` </div> ## invalidate Causes any `load` functions belonging to the currently active page to re-run if they depend on the `url` in question, via `fetch` or `depends`. Returns a `Promise` that resolves when the page is subsequently updated. If the argument is given as a `string` or `URL`, it must resolve to the same URL that was passed to `fetch` or `depends` (including query parameters). To create a custom identifier, use a string beginning with `[a-z]+:` (e.g. `custom:state`) — this is a valid URL. The `function` argument can be used define a custom predicate. It receives the full `URL` and causes `load` to rerun if `true` is returned. This can be useful if you want to invalidate based on a pattern instead of a exact match. ```ts // Example: Match '/path' regardless of the query parameters import { invalidate } from '$app/navigation'; invalidate((url) => url.pathname === '/path'); ``` <div class="ts-block"> ```dts function invalidate( resource: string | URL | ((url: URL) => boolean) ): Promise<void>; ``` </div> ## invalidateAll Causes all `load` functions belonging to the currently active page to re-run. Returns a `Promise` that resolves when the page is subsequently updated. <div class="ts-block"> ```dts function invalidateAll(): Promise<void>; ``` </div> ## onNavigate A lifecycle function that runs the supplied `callback` immediately before we navigate to a new URL except during full-page navigations. If you return a `Promise`, SvelteKit will wait for it to resolve before completing the navigation. This allows you to — for example — use `document.startViewTransition`. Avoid promises that are slow to resolve, since navigation will appear stalled to the user. If a function (or a `Promise` that resolves to a function) is returned from the callback, it will be called once the DOM has updated. `onNavigate` must be called during a component initialization. It remains active as long as the component is mounted. <div class="ts-block"> ```dts function onNavigate( callback: ( navigation: import('@sveltejs/kit').OnNavigate ) => MaybePromise<(() => void) | void> ): void; ``` </div> ## preloadCode Programmatically imports the code for routes that haven't yet been fetched. Typically, you might call this to speed up subsequent navigation. You can specify routes by any matching pathname such as `/about` (to match `src/routes/about/+page.svelte`) or `/blog/*` (to match `src/routes/blog/[slug]/+page.svelte`). Unlike `preloadData`, this won't call `load` functions. Returns a Promise that resolves when the modules have been imported. <div class="ts-block"> ```dts function preloadCode(pathname: string): Promise<void>; ``` </div> ## preloadData Programmatically preloads the given page, which means 1. ensuring that the code for the page is loaded, and 2. calling the page's load function with the appropriate options. This is the same behaviour that SvelteKit triggers when the user taps or mouses over an `<a>` element with `data-sveltekit-preload-data`. If the next navigation is to `href`, the values returned from load will be used, making navigation instantaneous. Returns a Promise that resolves with the result of running the new route's `load` functions once the preload is complete. <div class="ts-block"> ```dts function preloadData(href: string): Promise< | { type: 'loaded'; status: number; data: Record<string, any>; } | { type: 'redirect'; location: string; } >; ``` </div> ## pushState Programmatically create a new history entry with the given `page.state`. To use the current URL, you can pass `''` as the first argument. Used for [shallow routing](/docs/kit/shallow-routing). <div class="ts-block"> ```dts function pushState( url: string | URL, state: App.PageState ): void; ``` </div> ## replaceState Programmatically replace the current history entry with the given `page.state`. To use the current URL, you can pass `''` as the first argument. Used for [shallow routing](/docs/kit/shallow-routing). <div class="ts-block"> ```dts function replaceState( url: string | URL, state: App.PageState ): void; ``` </div>

# $app/paths

```js // @noErrors import { assets, base, resolveRoute } from '$app/paths'; ``` ## assets An absolute path that matches [`config.kit.paths.assets`](/docs/kit/configuration#paths). <div class="ts-block"> ```dts let assets: | '' | `https://${string}` | `http://${string}` | '/_svelte_kit_assets'; ``` </div> ## base A string that matches [`config.kit.paths.base`](/docs/kit/configuration#paths). Example usage: `<a href="{base}/your-page">Link</a>` <div class="ts-block"> ```dts let base: '' | `/${string}`; ``` </div> ## resolveRoute Populate a route ID with params to resolve a pathname. ```js // @errors: 7031 import { resolveRoute } from '$app/paths'; resolveRoute( `/blog/[slug]/[...somethingElse]`, { slug: 'hello-world', somethingElse: 'something/else' } ); // `/blog/hello-world/something/else` ``` <div class="ts-block"> ```dts function resolveRoute( id: string, params: Record<string, string | undefined> ): string; ``` </div>

# $app/server

```js // @noErrors import { read } from '$app/server'; ``` ## read <blockquote class="since note"> Available since 2.4.0 </blockquote> Read the contents of an imported asset from the filesystem ```js // @errors: 7031 import { read } from '$app/server'; import somefile from './somefile.txt'; const asset = read(somefile); const text = await asset.text(); ``` <div class="ts-block"> ```dts function read(asset: string): Response; ``` </div>

# $app/state

SvelteKit makes three read-only state objects available via the `$app/state` module — `page`, `navigating` and `updated`. > This module was added in 2.12. If you're using an earlier version of SvelteKit, use [`$app/stores`]($app-stores) instead. ```js // @noErrors import { navigating, page, updated } from '$app/state'; ``` ## navigating A read-only object representing an in-progress navigation, with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties. Values are `null` when no navigation is occurring, or during server rendering. <div class="ts-block"> ```dts const navigating: | import('@sveltejs/kit').Navigation | { from: null; to: null; type: null; willUnload: null; delta: null; complete: null; }; ``` </div> ## page A read-only reactive object with information about the current page, serving several use cases: - retrieving the combined `data` of all pages/layouts anywhere in your component tree (also see [loading data](/docs/kit/load)) - retrieving the current value of the `form` prop anywhere in your component tree (also see [form actions](/docs/kit/form-actions)) - retrieving the page state that was set through `goto`, `pushState` or `replaceState` (also see [goto](/docs/kit/$app-navigation#goto) and [shallow routing](/docs/kit/shallow-routing)) - retrieving metadata such as the URL you're on, the current route and its parameters, and whether or not there was an error ```svelte <!--- file: +layout.svelte ---> <script> import { page } from '$app/state'; </script> <p>Currently at {page.url.pathname}</p> {#if page.error} <span class="red">Problem detected</span> {:else} <span class="small">All systems operational</span> {/if} ``` Changes to `page` are available exclusively with runes. (The legacy reactivity syntax will not reflect any changes) ```svelte <!--- file: +page.svelte ---> <script> import { page } from '$app/state'; const id = $derived(page.params.id); // This will correctly update id for usage on this page $: badId = page.params.id; // Do not use; will never update after initial load </script> ``` On the server, values can only be read during rendering (in other words _not_ in e.g. `load` functions). In the browser, the values can be read at any time. <div class="ts-block"> ```dts const page: import('@sveltejs/kit').Page; ``` </div> ## updated A read-only reactive value that's initially `false`. If [`version.pollInterval`](/docs/kit/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update `current` to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling. <div class="ts-block"> ```dts const updated: { get current(): boolean; check(): Promise<boolean>; }; ``` </div>

# $app/stores

This module contains store-based equivalents of the exports from [`$app/state`]($app-state). If you're using SvelteKit 2.12 or later, use that module instead. ```js // @noErrors import { getStores, navigating, page, updated } from '$app/stores'; ``` ## getStores <div class="ts-block"> ```dts function getStores(): { page: typeof page; navigating: typeof navigating; updated: typeof updated; }; ``` </div> ## navigating <blockquote class="tag deprecated note"> Use `navigating` from `$app/state` instead (requires Svelte 5, [see docs for more info](/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) </blockquote> A readable store. When navigating starts, its value is a `Navigation` object with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties. When navigating finishes, its value reverts to `null`. On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. <div class="ts-block"> ```dts const navigating: import('svelte/store').Readable< import('@sveltejs/kit').Navigation | null >; ``` </div> ## page <blockquote class="tag deprecated note"> Use `page` from `$app/state` instead (requires Svelte 5, [see docs for more info](/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) </blockquote> A readable store whose value contains page data. On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. <div class="ts-block"> ```dts const page: import('svelte/store').Readable< import('@sveltejs/kit').Page >; ``` </div> ## updated <blockquote class="tag deprecated note"> Use `updated` from `$app/state` instead (requires Svelte 5, [see docs for more info](/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated)) </blockquote> A readable store whose initial value is `false`. If [`version.pollInterval`](/docs/kit/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling. On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. <div class="ts-block"> ```dts const updated: import('svelte/store').Readable<boolean> & { check(): Promise<boolean>; }; ``` </div>

# $env/dynamic/private

This module provides access to runtime environment variables, as defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](/docs/kit/cli)), this is equivalent to `process.env`. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](/docs/kit/configuration#env) (if configured). This module cannot be imported into client-side code. Dynamic environment variables cannot be used during prerendering. ```ts import { env } from '$env/dynamic/private'; console.log(env.DEPLOYMENT_SPECIFIC_VARIABLE); ``` > In `dev`, `$env/dynamic` always includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter.

# $env/dynamic/public

Similar to [`$env/dynamic/private`](/docs/kit/$env-dynamic-private), but only includes variables that begin with [`config.kit.env.publicPrefix`](/docs/kit/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code. Note that public dynamic environment variables must all be sent from the server to the client, causing larger network requests — when possible, use `$env/static/public` instead. Dynamic environment variables cannot be used during prerendering. ```ts import { env } from '$env/dynamic/public'; console.log(env.PUBLIC_DEPLOYMENT_SPECIFIC_VARIABLE); ```

# $env/static/private

Environment variables [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env`. Like [`$env/dynamic/private`](/docs/kit/$env-dynamic-private), this module cannot be imported into client-side code. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](/docs/kit/configuration#env) (if configured). _Unlike_ [`$env/dynamic/private`](/docs/kit/$env-dynamic-private), the values exported from this module are statically injected into your bundle at build time, enabling optimisations like dead code elimination. ```ts import { API_KEY } from '$env/static/private'; ``` Note that all environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed: ``` MY_FEATURE_FLAG="" ``` You can override `.env` values from the command line like so: ```bash MY_FEATURE_FLAG="enabled" npm run dev ```

# $env/static/public

Similar to [`$env/static/private`](/docs/kit/$env-static-private), except that it only includes environment variables that begin with [`config.kit.env.publicPrefix`](/docs/kit/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code. Values are replaced statically at build time. ```ts import { PUBLIC_BASE_URL } from '$env/static/public'; ```

# $lib

SvelteKit automatically makes files under `src/lib` available using the `$lib` import alias. You can change which directory this alias points to in your [config file](configuration#files). ```svelte <!--- file: src/lib/Component.svelte ---> A reusable component ``` ```svelte <!--- file: src/routes/+page.svelte ---> <script> import Component from '$lib/Component.svelte'; </script> <Component /> ```

# $service-worker

```js // @noErrors import { base, build, files, prerendered, version } from '$service-worker'; ``` This module is only available to [service workers](/docs/kit/service-workers). ## base The `base` path of the deployment. Typically this is equivalent to `config.kit.paths.base`, but it is calculated from `location.pathname` meaning that it will continue to work correctly if the site is deployed to a subdirectory. Note that there is a `base` but no `assets`, since service workers cannot be used if `config.kit.paths.assets` is specified. <div class="ts-block"> ```dts const base: string; ``` </div> ## build An array of URL strings representing the files generated by Vite, suitable for caching with `cache.addAll(build)`. During development, this is an empty array. <div class="ts-block"> ```dts const build: string[]; ``` </div> ## files An array of URL strings representing the files in your static directory, or whatever directory is specified by `config.kit.files.assets`. You can customize which files are included from `static` directory using [`config.kit.serviceWorker.files`](/docs/kit/configuration) <div class="ts-block"> ```dts const files: string[]; ``` </div> ## prerendered An array of pathnames corresponding to prerendered pages and endpoints. During development, this is an empty array. <div class="ts-block"> ```dts const prerendered: string[]; ``` </div> ## version See [`config.kit.version`](/docs/kit/configuration#version). It's useful for generating unique cache names inside your service worker, so that a later deployment of your app can invalidate old caches. <div class="ts-block"> ```dts const version: string; ``` </div>

# Configuration

Your project's configuration lives in a `svelte.config.js` file at the root of your project. As well as SvelteKit, this config object is used by other tooling that integrates with Svelte such as editor extensions. ```js /// file: svelte.config.js // @filename: ambient.d.ts declare module '@sveltejs/adapter-auto' { const plugin: () => import('@sveltejs/kit').Adapter; export default plugin; } // @filename: index.js // ---cut--- import adapter from '@sveltejs/adapter-auto'; /** @type {import('@sveltejs/kit').Config} */ const config = { kit: { adapter: adapter() } }; export default config; ``` ## Config <div class="ts-block"> ```dts interface Config {/*…*/} ``` <div class="ts-block-property"> ```dts compilerOptions?: CompileOptions; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `{}` </div> Options passed to [`svelte.compile`](/docs/svelte/svelte-compiler#CompileOptions). </div> </div> <div class="ts-block-property"> ```dts extensions?: string[]; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `[".svelte"]` </div> List of file extensions that should be treated as Svelte files. </div> </div> <div class="ts-block-property"> ```dts kit?: KitConfig; ``` <div class="ts-block-property-details"> SvelteKit options </div> </div> <div class="ts-block-property"> ```dts preprocess?: any; ``` <div class="ts-block-property-details"> Preprocessor options, if any. Preprocessing can alternatively also be done through Vite's preprocessor capabilities. </div> </div> <div class="ts-block-property"> ```dts vitePlugin?: PluginOptions; ``` <div class="ts-block-property-details"> `vite-plugin-svelte` plugin options. </div> </div> <div class="ts-block-property"> ```dts [key: string]: any; ``` <div class="ts-block-property-details"> Any additional options required by tooling that integrates with Svelte. </div> </div></div> ## KitConfig The `kit` property configures SvelteKit, and can have the following properties: ## adapter <div class="ts-block-property-bullets"> - <span class="tag">default</span> `undefined` </div> Your [adapter](/docs/kit/adapters) is run when executing `vite build`. It determines how the output is converted for different platforms. <div class="ts-block-property-children"> </div> ## alias <div class="ts-block-property-bullets"> - <span class="tag">default</span> `{}` </div> An object containing zero or more aliases used to replace values in `import` statements. These aliases are automatically passed to Vite and TypeScript. ```js // @errors: 7031 /// file: svelte.config.js /** @type {import('@sveltejs/kit').Config} */ const config = { kit: { alias: { // this will match a file 'my-file': 'path/to/my-file.js', // this will match a directory and its contents // (`my-directory/x` resolves to `path/to/my-directory/x`) 'my-directory': 'path/to/my-directory', // an alias ending /* will only match // the contents of a directory, not the directory itself 'my-directory/*': 'path/to/my-directory/*' } } }; ``` <div class="ts-block-property-children"> </div> ## appDir <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"_app"` </div> The directory where SvelteKit keeps its stuff, including static assets (such as JS and CSS) and internally-used routes. If `paths.assets` is specified, there will be two app directories — `${paths.assets}/${appDir}` and `${paths.base}/${appDir}`. <div class="ts-block-property-children"> </div> ## csp <div class="ts-block-property-bullets"> </div> [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) configuration. CSP helps to protect your users against cross-site scripting (XSS) attacks, by limiting the places resources can be loaded from. For example, a configuration like this... ```js // @errors: 7031 /// file: svelte.config.js /** @type {import('@sveltejs/kit').Config} */ const config = { kit: { csp: { directives: { 'script-src': ['self'] }, // must be specified with either the `report-uri` or `report-to` directives, or both reportOnly: { 'script-src': ['self'], 'report-uri': ['/'] } } } }; export default config; ``` ...would prevent scripts loading from external sites. SvelteKit will augment the specified directives with nonces or hashes (depending on `mode`) for any inline styles and scripts it generates. To add a nonce for scripts and links manually included in `src/app.html`, you may use the placeholder `%sveltekit.nonce%` (for example `<script nonce="%sveltekit.nonce%">`). When pages are prerendered, the CSP header is added via a `<meta http-equiv>` tag (note that in this case, `frame-ancestors`, `report-uri` and `sandbox` directives will be ignored). If this level of configuration is insufficient and you have more dynamic requirements, you can use the [`handle` hook](/docs/kit/hooks#Server-hooks-handle) to roll your own CSP. <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors mode?: 'hash' | 'nonce' | 'auto'; ``` <div class="ts-block-property-details"> Whether to use hashes or nonces to restrict `<script>` and `<style>` elements. `'auto'` will use hashes for prerendered pages, and nonces for dynamically rendered pages. </div> </div> <div class="ts-block-property"> ```ts // @noErrors directives?: CspDirectives; ``` <div class="ts-block-property-details"> Directives that will be added to `Content-Security-Policy` headers. </div> </div> <div class="ts-block-property"> ```ts // @noErrors reportOnly?: CspDirectives; ``` <div class="ts-block-property-details"> Directives that will be added to `Content-Security-Policy-Report-Only` headers. </div> </div> </div> ## csrf <div class="ts-block-property-bullets"> </div> Protection against [cross-site request forgery (CSRF)](https://owasp.org/www-community/attacks/csrf) attacks. <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors checkOrigin?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `true` </div> Whether to check the incoming `origin` header for `POST`, `PUT`, `PATCH`, or `DELETE` form submissions and verify that it matches the server's origin. To allow people to make `POST`, `PUT`, `PATCH`, or `DELETE` requests with a `Content-Type` of `application/x-www-form-urlencoded`, `multipart/form-data`, or `text/plain` to your app from other origins, you will need to disable this option. Be careful! </div> </div> </div> ## embedded <div class="ts-block-property-bullets"> - <span class="tag">default</span> `false` </div> Whether or not the app is embedded inside a larger app. If `true`, SvelteKit will add its event listeners related to navigation etc on the parent of `%sveltekit.body%` instead of `window`, and will pass `params` from the server rather than inferring them from `location.pathname`. Note that it is generally not supported to embed multiple SvelteKit apps on the same page and use client-side SvelteKit features within them (things such as pushing to the history state assume a single instance). <div class="ts-block-property-children"> </div> ## env <div class="ts-block-property-bullets"> </div> Environment variable configuration <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors dir?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"."` </div> The directory to search for `.env` files. </div> </div> <div class="ts-block-property"> ```ts // @noErrors publicPrefix?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"PUBLIC_"` </div> A prefix that signals that an environment variable is safe to expose to client-side code. See [`$env/static/public`](/docs/kit/$env-static-public) and [`$env/dynamic/public`](/docs/kit/$env-dynamic-public). Note that Vite's [`envPrefix`](https://vitejs.dev/config/shared-options.html#envprefix) must be set separately if you are using Vite's environment variable handling - though use of that feature should generally be unnecessary. </div> </div> <div class="ts-block-property"> ```ts // @noErrors privatePrefix?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `""` - <span class="tag since">available since</span> v1.21.0 </div> A prefix that signals that an environment variable is unsafe to expose to client-side code. Environment variables matching neither the public nor the private prefix will be discarded completely. See [`$env/static/private`](/docs/kit/$env-static-private) and [`$env/dynamic/private`](/docs/kit/$env-dynamic-private). </div> </div> </div> ## files <div class="ts-block-property-bullets"> </div> Where to find various files within your project. <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors assets?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"static"` </div> a place to put static files that should have stable URLs and undergo no processing, such as `favicon.ico` or `manifest.json` </div> </div> <div class="ts-block-property"> ```ts // @noErrors hooks?: {/*…*/} ``` <div class="ts-block-property-details"> <div class="ts-block-property-children"><div class="ts-block-property"> ```ts // @noErrors client?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"src/hooks.client"` </div> The location of your client [hooks](/docs/kit/hooks). </div> </div> <div class="ts-block-property"> ```ts // @noErrors server?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"src/hooks.server"` </div> The location of your server [hooks](/docs/kit/hooks). </div> </div> <div class="ts-block-property"> ```ts // @noErrors universal?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"src/hooks"` - <span class="tag since">available since</span> v2.3.0 </div> The location of your universal [hooks](/docs/kit/hooks). </div> </div></div> </div> </div> <div class="ts-block-property"> ```ts // @noErrors lib?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"src/lib"` </div> your app's internal library, accessible throughout the codebase as `$lib` </div> </div> <div class="ts-block-property"> ```ts // @noErrors params?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"src/params"` </div> a directory containing [parameter matchers](/docs/kit/advanced-routing#Matching) </div> </div> <div class="ts-block-property"> ```ts // @noErrors routes?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"src/routes"` </div> the files that define the structure of your app (see [Routing](/docs/kit/routing)) </div> </div> <div class="ts-block-property"> ```ts // @noErrors serviceWorker?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"src/service-worker"` </div> the location of your service worker's entry point (see [Service workers](/docs/kit/service-workers)) </div> </div> <div class="ts-block-property"> ```ts // @noErrors appTemplate?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"src/app.html"` </div> the location of the template for HTML responses </div> </div> <div class="ts-block-property"> ```ts // @noErrors errorTemplate?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"src/error.html"` </div> the location of the template for fallback error responses </div> </div> </div> ## inlineStyleThreshold <div class="ts-block-property-bullets"> - <span class="tag">default</span> `0` </div> Inline CSS inside a `<style>` block at the head of the HTML. This option is a number that specifies the maximum length of a CSS file in UTF-16 code units, as specified by the [String.length](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length) property, to be inlined. All CSS files needed for the page and smaller than this value are merged and inlined in a `<style>` block. <div class="ts-block-property-children"> </div> ## moduleExtensions <div class="ts-block-property-bullets"> - <span class="tag">default</span> `[".js", ".ts"]` </div> An array of file extensions that SvelteKit will treat as modules. Files with extensions that match neither `config.extensions` nor `config.kit.moduleExtensions` will be ignored by the router. <div class="ts-block-property-children"> </div> ## outDir <div class="ts-block-property-bullets"> - <span class="tag">default</span> `".svelte-kit"` </div> The directory that SvelteKit writes files to during `dev` and `build`. You should exclude this directory from version control. <div class="ts-block-property-children"> </div> ## output <div class="ts-block-property-bullets"> </div> Options related to the build output format <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors preloadStrategy?: 'modulepreload' | 'preload-js' | 'preload-mjs'; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"modulepreload"` - <span class="tag since">available since</span> v1.8.4 </div> SvelteKit will preload the JavaScript modules needed for the initial page to avoid import 'waterfalls', resulting in faster application startup. There are three strategies with different trade-offs: - `modulepreload` - uses `<link rel="modulepreload">`. This delivers the best results in Chromium-based browsers, in Firefox 115+, and Safari 17+. It is ignored in older browsers. - `preload-js` - uses `<link rel="preload">`. Prevents waterfalls in Chromium and Safari, but Chromium will parse each module twice (once as a script, once as a module). Causes modules to be requested twice in Firefox. This is a good setting if you want to maximise performance for users on iOS devices at the cost of a very slight degradation for Chromium users. - `preload-mjs` - uses `<link rel="preload">` but with the `.mjs` extension which prevents double-parsing in Chromium. Some static webservers will fail to serve .mjs files with a `Content-Type: application/javascript` header, which will cause your application to break. If that doesn't apply to you, this is the option that will deliver the best performance for the largest number of users, until `modulepreload` is more widely supported. </div> </div> <div class="ts-block-property"> ```ts // @noErrors bundleStrategy?: 'split' | 'single' | 'inline'; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `'split'` - <span class="tag since">available since</span> v2.13.0 </div> The bundle strategy option affects how your app's JavaScript and CSS files are loaded. - If `'split'`, splits the app up into multiple .js/.css files so that they are loaded lazily as the user navigates around the app. This is the default, and is recommended for most scenarios. - If `'single'`, creates just one .js bundle and one .css file containing code for the entire app. - If `'inline'`, inlines all JavaScript and CSS of the entire app into the HTML. The result is usable without a server (i.e. you can just open the file in your browser). When using `'split'`, you can also adjust the bundling behaviour by setting [`output.experimentalMinChunkSize`](https://rollupjs.org/configuration-options/#output-experimentalminchunksize) and [`output.manualChunks`](https://rollupjs.org/configuration-options/#output-manualchunks) inside your Vite config's [`build.rollupOptions`](https://vite.dev/config/build-options.html#build-rollupoptions). If you want to inline your assets, you'll need to set Vite's [`build.assetsInlineLimit`](https://vite.dev/config/build-options.html#build-assetsinlinelimit) option to an appropriate size then import your assets through Vite. ```js // @errors: 7031 /// file: vite.config.js import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [sveltekit()], build: { // inline all imported assets assetsInlineLimit: Infinity } }); ``` ```svelte /// file: src/routes/+layout.svelte <script> // import the asset through Vite import favicon from './favicon.png'; </script> <svelte:head> <!-- this asset will be inlined as a base64 URL --> <link rel="icon" href={favicon} /> </svelte:head> ``` </div> </div> </div> ## paths <div class="ts-block-property-bullets"> </div> <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors assets?: '' | `http://${string}` | `https://${string}`; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `""` </div> An absolute path that your app's files are served from. This is useful if your files are served from a storage bucket of some kind. </div> </div> <div class="ts-block-property"> ```ts // @noErrors base?: '' | `/${string}`; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `""` </div> A root-relative path that must start, but not end with `/` (e.g. `/base-path`), unless it is the empty string. This specifies where your app is served from and allows the app to live on a non-root path. Note that you need to prepend all your root-relative links with the base value or they will point to the root of your domain, not your `base` (this is how the browser works). You can use [`base` from `$app/paths`](/docs/kit/$app-paths#base) for that: `<a href="{base}/your-page">Link</a>`. If you find yourself writing this often, it may make sense to extract this into a reusable component. </div> </div> <div class="ts-block-property"> ```ts // @noErrors relative?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `true` - <span class="tag since">available since</span> v1.9.0 </div> Whether to use relative asset paths. If `true`, `base` and `assets` imported from `$app/paths` will be replaced with relative asset paths during server-side rendering, resulting in more portable HTML. If `false`, `%sveltekit.assets%` and references to build artifacts will always be root-relative paths, unless `paths.assets` is an external URL [Single-page app](/docs/kit/single-page-apps) fallback pages will always use absolute paths, regardless of this setting. If your app uses a `<base>` element, you should set this to `false`, otherwise asset URLs will incorrectly be resolved against the `<base>` URL rather than the current page. In 1.0, `undefined` was a valid value, which was set by default. In that case, if `paths.assets` was not external, SvelteKit would replace `%sveltekit.assets%` with a relative path and use relative paths to reference build artifacts, but `base` and `assets` imported from `$app/paths` would be as specified in your config. </div> </div> </div> ## prerender <div class="ts-block-property-bullets"> </div> See [Prerendering](/docs/kit/page-options#prerender). <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors concurrency?: number; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `1` </div> How many pages can be prerendered simultaneously. JS is single-threaded, but in cases where prerendering performance is network-bound (for example loading content from a remote CMS) this can speed things up by processing other tasks while waiting on the network response. </div> </div> <div class="ts-block-property"> ```ts // @noErrors crawl?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `true` </div> Whether SvelteKit should find pages to prerender by following links from `entries`. </div> </div> <div class="ts-block-property"> ```ts // @noErrors entries?: Array<'*' | `/${string}`>; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `["*"]` </div> An array of pages to prerender, or start crawling from (if `crawl: true`). The `*` string includes all routes containing no required `[parameters]` with optional parameters included as being empty (since SvelteKit doesn't know what value any parameters should have). </div> </div> <div class="ts-block-property"> ```ts // @noErrors handleHttpError?: PrerenderHttpErrorHandlerValue; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"fail"` - <span class="tag since">available since</span> v1.15.7 </div> How to respond to HTTP errors encountered while prerendering the app. - `'fail'` — fail the build - `'ignore'` - silently ignore the failure and continue - `'warn'` — continue, but print a warning - `(details) => void` — a custom error handler that takes a `details` object with `status`, `path`, `referrer`, `referenceType` and `message` properties. If you `throw` from this function, the build will fail ```js // @errors: 7031 /// file: svelte.config.js /** @type {import('@sveltejs/kit').Config} */ const config = { kit: { prerender: { handleHttpError: ({ path, referrer, message }) => { // ignore deliberate link to shiny 404 page if (path === '/not-found' && referrer === '/blog/how-we-built-our-404-page') { return; } // otherwise fail the build throw new Error(message); } } } }; ``` </div> </div> <div class="ts-block-property"> ```ts // @noErrors handleMissingId?: PrerenderMissingIdHandlerValue; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"fail"` - <span class="tag since">available since</span> v1.15.7 </div> How to respond when hash links from one prerendered page to another don't correspond to an `id` on the destination page. - `'fail'` — fail the build - `'ignore'` - silently ignore the failure and continue - `'warn'` — continue, but print a warning - `(details) => void` — a custom error handler that takes a `details` object with `path`, `id`, `referrers` and `message` properties. If you `throw` from this function, the build will fail </div> </div> <div class="ts-block-property"> ```ts // @noErrors handleEntryGeneratorMismatch?: PrerenderEntryGeneratorMismatchHandlerValue; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"fail"` - <span class="tag since">available since</span> v1.16.0 </div> How to respond when an entry generated by the `entries` export doesn't match the route it was generated from. - `'fail'` — fail the build - `'ignore'` - silently ignore the failure and continue - `'warn'` — continue, but print a warning - `(details) => void` — a custom error handler that takes a `details` object with `generatedFromId`, `entry`, `matchedId` and `message` properties. If you `throw` from this function, the build will fail </div> </div> <div class="ts-block-property"> ```ts // @noErrors origin?: string; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"http://sveltekit-prerender"` </div> The value of `url.origin` during prerendering; useful if it is included in rendered content. </div> </div> </div> ## router <div class="ts-block-property-bullets"> </div> <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors type?: 'pathname' | 'hash'; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"pathname"` - <span class="tag since">available since</span> v2.14.0 </div> What type of client-side router to use. - `'pathname'` is the default and means the current URL pathname determines the route - `'hash'` means the route is determined by `location.hash`. In this case, SSR and prerendering are disabled. This is only recommended if `pathname` is not an option, for example because you don't control the webserver where your app is deployed. It comes with some caveats: you can't use server-side rendering (or indeed any server logic), and you have to make sure that the links in your app all start with #/, or they won't work. Beyond that, everything works exactly like a normal SvelteKit app. </div> </div> <div class="ts-block-property"> ```ts // @noErrors resolution?: 'client' | 'server'; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `"client"` - <span class="tag since">available since</span> v2.17.0 </div> How to determine which route to load when navigating to a new page. By default, SvelteKit will serve a route manifest to the browser. When navigating, this manifest is used (along with the `reroute` hook, if it exists) to determine which components to load and which `load` functions to run. Because everything happens on the client, this decision can be made immediately. The drawback is that the manifest needs to be loaded and parsed before the first navigation can happen, which may have an impact if your app contains many routes. Alternatively, SvelteKit can determine the route on the server. This means that for every navigation to a path that has not yet been visited, the server will be asked to determine the route. This has several advantages: - The client does not need to load the routing manifest upfront, which can lead to faster initial page loads - The list of routes is hidden from public view - The server has an opportunity to intercept each navigation (for example through a middleware), enabling (for example) A/B testing opaque to SvelteKit The drawback is that for unvisited paths, resolution will take slightly longer (though this is mitigated by [preloading](/docs/kit/link-options#data-sveltekit-preload-data)). </div> </div> </div> ## serviceWorker <div class="ts-block-property-bullets"> </div> <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors register?: boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `true` </div> Whether to automatically register the service worker, if it exists. </div> </div> <div class="ts-block-property"> ```ts // @noErrors files?(filepath: string): boolean; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `(filename) => !/\.DS_Store/.test(filename)` </div> Determine which files in your `static` directory will be available in `$service-worker.files`. </div> </div> </div> ## typescript <div class="ts-block-property-bullets"> </div> <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors config?: (config: Record<string, any>) => Record<string, any> | void; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `(config) => config` - <span class="tag since">available since</span> v1.3.0 </div> A function that allows you to edit the generated `tsconfig.json`. You can mutate the config (recommended) or return a new one. This is useful for extending a shared `tsconfig.json` in a monorepo root, for example. </div> </div> </div> ## version <div class="ts-block-property-bullets"> </div> Client-side navigation can be buggy if you deploy a new version of your app while people are using it. If the code for the new page is already loaded, it may have stale content; if it isn't, the app's route manifest may point to a JavaScript file that no longer exists. SvelteKit helps you solve this problem through version management. If SvelteKit encounters an error while loading the page and detects that a new version has been deployed (using the `name` specified here, which defaults to a timestamp of the build) it will fall back to traditional full-page navigation. Not all navigations will result in an error though, for example if the JavaScript for the next page is already loaded. If you still want to force a full-page navigation in these cases, use techniques such as setting the `pollInterval` and then using `beforeNavigate`: ```html /// file: +layout.svelte <script> import { beforeNavigate } from '$app/navigation'; import { updated } from '$app/state'; beforeNavigate(({ willUnload, to }) => { if (updated.current && !willUnload && to?.url) { location.href = to.url.href; } }); </script> ``` If you set `pollInterval` to a non-zero value, SvelteKit will poll for new versions in the background and set the value of [`updated.current`](/docs/kit/$app-state#updated) `true` when it detects one. <div class="ts-block-property-children"> <div class="ts-block-property"> ```ts // @noErrors name?: string; ``` <div class="ts-block-property-details"> The current app version string. If specified, this must be deterministic (e.g. a commit ref rather than `Math.random()` or `Date.now().toString()`), otherwise defaults to a timestamp of the build. For example, to use the current commit hash, you could do use `git rev-parse HEAD`: ```js // @errors: 7031 /// file: svelte.config.js import * as child_process from 'node:child_process'; export default { kit: { version: { name: child_process.execSync('git rev-parse HEAD').toString().trim() } } }; ``` </div> </div> <div class="ts-block-property"> ```ts // @noErrors pollInterval?: number; ``` <div class="ts-block-property-details"> <div class="ts-block-property-bullets"> - <span class="tag">default</span> `0` </div> The interval in milliseconds to poll for version changes. If this is `0`, no polling occurs. </div> </div> </div>

# Command Line Interface

SvelteKit projects use [Vite](https://vitejs.dev), meaning you'll mostly use its CLI (albeit via `npm run dev/build/preview` scripts): - `vite dev` — start a development server - `vite build` — build a production version of your app - `vite preview` — run the production version locally However SvelteKit includes its own CLI for initialising your project: ## svelte-kit sync `svelte-kit sync` creates the `tsconfig.json` and all generated types (which you can import as `./$types` inside routing files) for your project. When you create a new project, it is listed as the `prepare` script and will be run automatically as part of the npm lifecycle, so you should not ordinarily have to run this command.

# Types

## Generated types The `RequestHandler` and `Load` types both accept a `Params` argument allowing you to type the `params` object. For example this endpoint expects `foo`, `bar` and `baz` params: ```js /// file: src/routes/[foo]/[bar]/[baz]/+server.js // @errors: 2355 2322 1360 /** @type {import('@sveltejs/kit').RequestHandler<{ foo: string; bar: string; baz: string }>} */ export async function GET({ params }) { // ... } ``` Needless to say, this is cumbersome to write out, and less portable (if you were to rename the `[foo]` directory to `[qux]`, the type would no longer reflect reality). To solve this problem, SvelteKit generates `.d.ts` files for each of your endpoints and pages: ```ts /// file: .svelte-kit/types/src/routes/[foo]/[bar]/[baz]/$types.d.ts /// link: true import type * as Kit from '@sveltejs/kit'; type RouteParams = { foo: string; bar: string; baz: string; }; export type RequestHandler = Kit.RequestHandler<RouteParams>; export type PageLoad = Kit.Load<RouteParams>; ``` These files can be imported into your endpoints and pages as siblings, thanks to the [`rootDirs`](https://www.typescriptlang.org/tsconfig#rootDirs) option in your TypeScript configuration: ```js /// file: src/routes/[foo]/[bar]/[baz]/+server.js // @filename: $types.d.ts import type * as Kit from '@sveltejs/kit'; type RouteParams = { foo: string; bar: string; baz: string; } export type RequestHandler = Kit.RequestHandler<RouteParams>; // @filename: index.js // @errors: 2355 2322 // ---cut--- /** @type {import('./$types').RequestHandler} */ export async function GET({ params }) { // ... } ``` ```js /// file: src/routes/[foo]/[bar]/[baz]/+page.js // @filename: $types.d.ts import type * as Kit from '@sveltejs/kit'; type RouteParams = { foo: string; bar: string; baz: string; } export type PageLoad = Kit.Load<RouteParams>; // @filename: index.js // @errors: 2355 // ---cut--- /** @type {import('./$types').PageLoad} */ export async function load({ params, fetch }) { // ... } ``` The return types of the load functions are then available through the `$types` module as `PageData` and `LayoutData` respectively, while the union of the return values of all `Actions` is available as `ActionData`. Starting with version 2.16.0, two additional helper types are provided: `PageProps` defines `data: PageData`, as well as `form: ActionData`, when there are actions defined, while `LayoutProps` defines `data: LayoutData`, as well as `children: Snippet`. ```svelte <!--- file: src/routes/+page.svelte ---> <script> /** @type {import('./$types').PageProps} */ let { data, form } = $props(); </script> ``` > Before 2.16.0: > ```svelte > <!--- file: src/routes/+page.svelte ---> > <script> > /** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */ > let { data, form } = $props(); > </script> > ``` > > Using Svelte 4: > ```svelte > <!--- file: src/routes/+page.svelte ---> > <script> > /** @type {import('./$types').PageData} */ > export let data; > /** @type {import('./$types').ActionData} */ > export let form; > </script> > ``` > > `{ "extends": "./.svelte-kit/tsconfig.json" }` ### Default tsconfig.json The generated `.svelte-kit/tsconfig.json` file contains a mixture of options. Some are generated programmatically based on your project configuration, and should generally not be overridden without good reason: ```json /// file: .svelte-kit/tsconfig.json { "compilerOptions": { "paths": { "$lib": ["../src/lib"], "$lib/*": ["../src/lib/*"] }, "rootDirs": ["..", "./types"] }, "include": [ "ambient.d.ts", "non-ambient.d.ts", "./types/**/$types.d.ts", "../vite.config.js", "../vite.config.ts", "../src/**/*.js", "../src/**/*.ts", "../src/**/*.svelte", "../tests/**/*.js", "../tests/**/*.ts", "../tests/**/*.svelte" ], "exclude": [ "../node_modules/**", "../src/service-worker.js", "../src/service-worker/**/*.js", "../src/service-worker.ts", "../src/service-worker/**/*.ts", "../src/service-worker.d.ts", "../src/service-worker/**/*.d.ts" ] } ``` Others are required for SvelteKit to work properly, and should also be left untouched unless you know what you're doing: ```json /// file: .svelte-kit/tsconfig.json { "compilerOptions": { // this ensures that types are explicitly // imported with `import type`, which is // necessary as Svelte/Vite cannot // otherwise compile components correctly "verbatimModuleSyntax": true, // Vite compiles one TypeScript module // at a time, rather than compiling // the entire module graph "isolatedModules": true, // Tell TS it's used only for type-checking "noEmit": true, // This ensures both `vite build` // and `svelte-package` work correctly "lib": ["esnext", "DOM", "DOM.Iterable"], "moduleResolution": "bundler", "module": "esnext", "target": "esnext" } } ``` ## $lib This is a simple alias to `src/lib`, or whatever directory is specified as [`config.kit.files.lib`](configuration#files). It allows you to access common components and utility modules without `../../../../` nonsense. ### $lib/server A subdirectory of `$lib`. SvelteKit will prevent you from importing any modules in `$lib/server` into client-side code. See [server-only modules](server-only-modules). ## app.d.ts The `app.d.ts` file is home to the ambient types of your apps, i.e. types that are available without explicitly importing them. Always part of this file is the `App` namespace. This namespace contains several types that influence the shape of certain SvelteKit features you interact with. ## Error Defines the common shape of expected and unexpected errors. Expected errors are thrown using the `error` function. Unexpected errors are handled by the `handleError` hooks which should return this shape. <div class="ts-block"> ```dts interface Error {/*…*/} ``` <div class="ts-block-property"> ```dts message: string; ``` <div class="ts-block-property-details"></div> </div></div> ## Locals The interface that defines `event.locals`, which can be accessed in server [hooks](/docs/kit/hooks) (`handle`, and `handleError`), server-only `load` functions, and `+server.js` files. <div class="ts-block"> ```dts interface Locals {} ``` </div> ## PageData Defines the common shape of the [page.data state](/docs/kit/$app-state#page) and [$page.data store](/docs/kit/$app-stores#page) - that is, the data that is shared between all pages. The `Load` and `ServerLoad` functions in `./$types` will be narrowed accordingly. Use optional properties for data that is only present on specific pages. Do not add an index signature (`[key: string]: any`). <div class="ts-block"> ```dts interface PageData {} ``` </div> ## PageState The shape of the `page.state` object, which can be manipulated using the [`pushState`](/docs/kit/$app-navigation#pushState) and [`replaceState`](/docs/kit/$app-navigation#replaceState) functions from `$app/navigation`. <div class="ts-block"> ```dts interface PageState {} ``` </div> ## Platform If your adapter provides [platform-specific context](/docs/kit/adapters#Platform-specific-context) via `event.platform`, you can specify it here. <div class="ts-block"> ```dts interface Platform {} ``` </div>
# Start of the Svelte CLI documentation


# Overview

The command line interface (CLI), `sv`, is a toolkit for creating and maintaining Svelte applications. ## Usage The easiest way to run `sv` is with [`npx`](https://docs.npmjs.com/cli/v8/commands/npx) (or the equivalent command if you're using a different package manager — for example, `pnpx` if you're using [pnpm](https://pnpm.io/)): ```bash npx sv <command> <args> ``` If you're inside a project where `sv` is already installed, this will use the local installation, otherwise it will download the latest version and run it without installing it, which is particularly useful for [`sv create`](sv-create). ## Acknowledgements Thank you to [Christopher Brown](https://github.com/chbrown) who originally owned the `sv` name on npm for graciously allowing it to be used for the Svelte CLI. You can find the original `sv` package at [`@chbrown/sv`](https://www.npmjs.com/package/@chbrown/sv).

# sv create

`sv create` sets up a new SvelteKit project, with options to [setup additional functionality](sv-add#Official-add-ons). ## Usage ```bash npx sv create [options] [path] ``` ## Options ### `--template <name>` Which project template to use: - `minimal` — barebones scaffolding for your new app - `demo` — showcase app with a word guessing game that works without JavaScript - `library` — template for a Svelte library, set up with `svelte-package` ### `--types <option>` Whether and how to add typechecking to the project: - `ts` — default to `.ts` files and use `lang="ts"` for `.svelte` components - `jsdoc` — use [JSDoc syntax](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html) for types ### `--no-types` Prevent typechecking from being added. Not recommended! ### `--no-add-ons` Run the command without the interactive add-ons prompt ### `--no-install` Skip dependency installation <!-- ## Programmatic interface ```js // TODO: this gives type checking errors in the docs site when not commented out. Need to release sv, install it in the site, and uncomment this. // import { create } from 'sv'; // // todo: check if this is right // create(cwd, { // // add your options here // // todo: list available option // }); ``` -->

# sv add

`sv add` updates an existing project with new functionality. ## Usage ```bash npx sv add ``` ```bash npx sv add [add-ons] ``` You can select multiple space-separated add-ons from [the list below](#Official-add-ons), or you can use the interactive prompt. ## Options - `-C`, `--cwd` — path to the root of your Svelte(Kit) project - `--no-preconditions` — skip checking preconditions <!-- TODO what does this mean? --> - `--no-install` — skip dependency installation ## Official add-ons <!-- TODO this should be a separate section, each of these should have their own page --> - `drizzle` - `eslint` - `sveltekit-adapter` - `lucia` - `mdsvex` - `paraglide` - `playwright` - `prettier` - `storybook` - `tailwindcss` - `vitest`

# sv check

`sv check` finds errors and warnings in your project, such as: - unused CSS - accessibility hints - JavaScript/TypeScript compiler errors Requires Node 16 or later. ## Installation You will need to have the `svelte-check` package installed in your project: ```bash npm i -D svelte-check ``` ## Usage ```bash npx sv check ``` ## Options ### `--workspace <path>` Path to your workspace. All subdirectories except `node_modules` and those listed in `--ignore` are checked. ### `--output <format>` How to display errors and warnings. See [machine-readable output](#Machine-readable-output). - `human` - `human-verbose` - `machine` - `machine-verbose` ### `--watch` Keeps the process alive and watches for changes. ### `--preserveWatchOutput` Prevents the screen from being cleared in watch mode. ### `--tsconfig <path>` Pass a path to a `tsconfig` or `jsconfig` file. The path can be relative to the workspace path or absolute. Doing this means that only files matched by the `files`/`include`/`exclude` pattern of the config file are diagnosed. It also means that errors from TypeScript and JavaScript files are reported. If not given, will traverse upwards from the project directory looking for the next `jsconfig`/`tsconfig.json` file. ### `--no-tsconfig` Use this if you only want to check the Svelte files found in the current directory and below and ignore any `.js`/`.ts` files (they will not be type-checked) ### `--ignore <paths>` Files/folders to ignore, relative to workspace root. Paths should be comma-separated and quoted. Example: ```bash npx sv check --ignore "dist,build" ``` <!-- TODO what the hell does this mean? is it possible to use --tsconfig AND --no-tsconfig? if so what would THAT mean? --> Only has an effect when used in conjunction with `--no-tsconfig`. When used in conjunction with `--tsconfig`, this will only have effect on the files watched, not on the files that are diagnosed, which is then determined by the `tsconfig.json`. ### `--fail-on-warnings` If provided, warnings will cause `sv check` to exit with an error code. ### `--compiler-warnings <warnings>` A quoted, comma-separated list of `code:behaviour` pairs where `code` is a [compiler warning code](../svelte/compiler-warnings) and `behaviour` is either `ignore` or `error`: ```bash npx sv check --compiler-warnings "css_unused_selector:ignore,a11y_missing_attribute:error" ``` ### `--diagnostic-sources <sources>` A quoted, comma-separated list of sources that should run diagnostics on your code. By default, all are active: <!-- TODO would be nice to have a clearer definition of what these are --> - `js` (includes TypeScript) - `svelte` - `css` Example: ```bash npx sv check --diagnostic-sources "js,svelte" ``` ### `--threshold <level>` Filters the diagnostics: - `warning` (default) — both errors and warnings are shown - `error` — only errors are shown ## Troubleshooting [See the language-tools documentation](https://github.com/sveltejs/language-tools/blob/master/docs/README.md) for more information on preprocessor setup and other troubleshooting. ## Machine-readable output Setting the `--output` to `machine` or `machine-verbose` will format output in a way that is easier to read by machines, e.g. inside CI pipelines, for code quality checks, etc. Each row corresponds to a new record. Rows are made up of columns that are separated by a single space character. The first column of every row contains a timestamp in milliseconds which can be used for monitoring purposes. The second column gives us the "row type", based on which the number and types of subsequent columns may differ. The first row is of type `START` and contains the workspace folder (wrapped in quotes). Example: ``` 1590680325583 START "/home/user/language-tools/packages/language-server/test/plugins/typescript/testfiles" ``` Any number of `ERROR` or `WARNING` records may follow. Their structure is identical and depends on the output argument. If the argument is `machine` it will tell us the filename, the starting line and column numbers, and the error message. The filename is relative to the workspace directory. The filename and the message are both wrapped in quotes. Example: ``` 1590680326283 ERROR "codeactions.svelte" 1:16 "Cannot find module 'blubb' or its corresponding type declarations." 1590680326778 WARNING "imported-file.svelte" 0:37 "Component has unused export property 'prop'. If it is for external reference only, please consider using `export const prop`" ``` If the argument is `machine-verbose` it will tell us the filename, the starting line and column numbers, the ending line and column numbers, the error message, the code of diagnostic, the human-friendly description of the code and the human-friendly source of the diagnostic (eg. svelte/typescript). The filename is relative to the workspace directory. Each diagnostic is represented as an [ndjson](https://en.wikipedia.org/wiki/JSON_streaming#Newline-Delimited_JSON) line prefixed by the timestamp of the log. Example: ``` 1590680326283 {"type":"ERROR","fn":"codeaction.svelte","start":{"line":1,"character":16},"end":{"line":1,"character":23},"message":"Cannot find module 'blubb' or its corresponding type declarations.","code":2307,"source":"js"} 1590680326778 {"type":"WARNING","filename":"imported-file.svelte","start":{"line":0,"character":37},"end":{"line":0,"character":51},"message":"Component has unused export property 'prop'. If it is for external reference only, please consider using `export const prop`","code":"unused-export-let","source":"svelte"} ``` The output concludes with a `COMPLETED` message that summarizes total numbers of files, errors and warnings that were encountered during the check. Example: ``` 1590680326807 COMPLETED 20 FILES 21 ERRORS 1 WARNINGS 3 FILES_WITH_PROBLEMS ``` If the application experiences a runtime error, this error will appear as a `FAILURE` record. Example: ``` 1590680328921 FAILURE "Connection closed" ``` ## Credits - Vue's [VTI](https://github.com/vuejs/vetur/tree/master/vti) which laid the foundation for `svelte-check` ## FAQ ### Why is there no option to only check specific files (for example only staged files)? `svelte-check` needs to 'see' the whole project for checks to be valid. Suppose you renamed a component prop but didn't update any of the places where the prop is used — the usage sites are all errors now, but you would miss them if checks only ran on changed files.

# sv migrate

`sv migrate` migrates Svelte(Kit) codebases. It delegates to the [`svelte-migrate`](https://www.npmjs.com/package/svelte-migrate) package. Some migrations may annotate your codebase with tasks for completion that you can find by searching for `@migration`. ## Usage ```bash npx sv migrate ``` You can also specify a migration directly via the CLI: ```bash npx sv migrate [migration] ``` ## Migrations ### `app-state` Migrates `$app/stores` usage to `$app/state` in `.svelte` files. See the [migration guide](/docs/kit/migrating-to-sveltekit-2#SvelteKit-2.12:-$app-stores-deprecated) for more details. ### `svelte-5` Upgrades a Svelte 4 app to use Svelte 5, and updates individual components to use [runes](../svelte/what-are-runes) and other Svelte 5 syntax ([see migration guide](../svelte/v5-migration-guide)). ### `self-closing-tags` Replaces all the self-closing non-void elements in your `.svelte` files. See the [pull request](https://github.com/sveltejs/kit/pull/12128) for more details. ### `svelte-4` Upgrades a Svelte 3 app to use Svelte 4 ([see migration guide](../svelte/v4-migration-guide)). ### `sveltekit-2` Upgrades a SvelteKit 1 app to SvelteKit 2 ([see migration guide](../kit/migrating-to-sveltekit-2)). ### `package` Upgrades a library using `@sveltejs/package` version 1 to version 2. See the [pull request](https://github.com/sveltejs/kit/pull/8922) for more details. ### `routes` Upgrades a pre-release SvelteKit app to use the filesystem routing conventions in SvelteKit 1. See the [pull request](https://github.com/sveltejs/kit/discussions/5774) for more details.