This is the abridged developer documentation for Svelte and SvelteKit.
# Svelte documentation
## Svelte
You **MUST** use the Svelte 5 API unless explicitly tasked to write Svelte 4 syntax. If you don't know about the API yet, below is the most important information about it. Other syntax not explicitly listed like `{#if ...}` blocks stay the same, so you can reuse your Svelte 4 knowledge for these.
- to mark something a state you use the `$state` rune, e.g. instead of `let count = 0` you do `let count = $state(0)`
- to mark something as a derivation you use the `$derived` rune, e.g. instead of `$: double = count * 2` you do `const double = $derived(count * 2)`
- to create a side effect you use the `$effect` rune, e.g. instead of `$: console.log(double)`you do`$effect(() => console.log(double))`
- to create component props you use the `$props` rune, e.g. instead of `export let foo = true; export let bar;` you do `let { foo = true, bar } = $props();`
- when listening to dom events do not use colons as part of the event name anymore, e.g. instead of `` you do ``
### What are runes?
- Runes are built-in Svelte keywords (prefixed with `$`) that control the compiler. For example, you write `let message = $state('hello');` in a `.svelte` file.
- Do **NOT** treat runes like regular functions or import them; instead, use them as language keywords.
_In Svelte 4, this syntax did not exist—you relied on reactive declarations and stores; now runes are an integral part of the language._
### $state
- `$state` creates reactive variables that update the UI automatically. For example:
```svelte
```
- Do **NOT** complicate state management by wrapping it in custom objects; instead, update reactive variables directly.
_In Svelte 4, you created state with let, e.g. `let count = 0;`, now use the $state rune, e.g. `let count = $state(0);`._
- Arrays and objects become deeply reactive proxies. For example:
```js
let todos = $state([{ done: false, text: 'add more todos' }]);
todos[0].done = !todos[0].done;
```
- Do **NOT** destructure reactive proxies (e.g., `let { done } = todos[0];`), as this breaks reactivity; instead, access properties directly.
- Use `$state` in class fields for reactive properties. For example:
```js
class Todo {
done = $state(false);
text = $state('');
reset = () => {
this.text = '';
this.done = false;
};
}
```
### $state.raw
- `$state.raw` creates shallow state where mutations are not tracked. For example:
```js
let person = $state.raw({ name: 'Heraclitus', age: 49 });
// Instead of mutating:
// person.age += 1; // NO effect
person = { name: 'Heraclitus', age: 50 }; // Correct way to update
```
- Do **NOT** attempt to mutate properties on raw state; instead, reassign the entire object to trigger updates.
### $state.snapshot
- `$state.snapshot` produces a plain object copy of reactive state. For example:
```svelte
```
- **ONLY** use this if you are told there's a problem with passing reactive proxies to external APIs.
### Passing state into functions
- Pass-by-Value Semantics: Use getter functions to ensure functions access the current value of reactive state. For example:
```js
function add(getA, getB) {
return () => getA() + getB();
}
let a = 1,
b = 2;
let total = add(
() => a,
() => b
);
console.log(total());
```
- Do **NOT** assume that passing a reactive state variable directly maintains live updates; instead, pass getter functions.
_In Svelte 4, you often used stores with subscribe methods; now prefer getter functions with `$state` / `$derived` instead._
### $derived
- `$derived` computes reactive values based on dependencies. For example:
```svelte
```
- Do **NOT** introduce side effects in derived expressions; instead, keep them pure.
_In Svelte 4 you used `$:` for this, e.g. `$: doubled = count * 2;`, now use the $derived rune instead, e.g `let doubled = $derived(count * 2);`._
#### $derived.by
- Use `$derived.by` for multi-line or complex logic. For example:
```svelte
```
- Do **NOT** force complex logic into a single expression; instead, use `$derived.by` to keep code clear.
#### Overriding derived values
- You can reassign a derived value for features like optimistic UI. It will go back to the `$derived` value once an update in its dependencies happen. For example:
```svelte
```
- Do **NOT** try to override derived state via effects; instead, reassign directly when needed.
_In Svelte 4 you could use `$:` for that, e.g. `$: likes = post.likes; likes = 1`, now use the `$derived` instead, e.g. `let likes = $derived(post.likes); likes = 1;`._
### $effect
- `$effect` executes functions when reactive state changes. For example:
```svelte
```
- Do **NOT** use `$effect` for state synchronization; instead, use it only for side effects like logging or DOM manipulation.
_In Svelte 4, you used reactive statements (`$:`) for similar tasks, .e.g `$: console.log(size)`; now use the `$effect` rune instead, e.g. `$effect(() => console.log(size))` ._
#### Understanding lifecycle (for $effect)
- Effects run after the DOM updates and can return teardown functions. For example:
```svelte
```
- **Directive:** Do **NOT** ignore cleanup; instead, always return a teardown function when needed.
#### $effect.pre
- `$effect.pre` works like `$effect` with the only difference that it runs before the DOM updates. For example:
```svelte
```
- Do **NOT** use `$effect.pre` for standard post-update tasks; instead, reserve it for pre-DOM manipulation like autoscrolling.
#### $effect.tracking
- `$effect.tracking` indicates if code is running inside a reactive context. For example:
```svelte
```
- Do **NOT** misuse tracking information outside its intended debugging context; instead, use it to enhance reactive debugging.
_In Svelte 4, no equivalent existed; now this feature offers greater insight into reactivity._
#### $effect.root
- `$effect.root` creates a non-tracked scope for nested effects with manual cleanup. For example:
```svelte
```
- Do **NOT** expect root effects to auto-cleanup; instead, manage their teardown manually.
_In Svelte 4, manual cleanup required explicit lifecycle hooks; now `$effect.root` centralizes this control._
### $props
- Use `$props` to access component inputs. For example:
```svelte
This component is {adjective}
```
- Do **NOT** mutate props directly; instead, use callbacks or bindable props to communicate changes.
_In Svelte 4, props were declared with `export let foo`; now you use `$props` rune, e.g. `let { foo } = $props()`._
- Declare fallback values via destructuring. For example:
```js
let { adjective = 'happy' } = $props();
```
- Rename props to avoid reserved keywords. For example:
```js
let { super: trouper } = $props();
```
- Use rest syntax to collect all remaining props. For example:
```js
let { a, b, ...others } = $props();
```
#### $props.id()
- Generate a unique ID for the component instance. For example:
```svelte
```
- Do **NOT** manually generate or guess IDs; instead, rely on `$props.id()` for consistency.
### $bindable
- Mark props as bindable to allow two-way data flow. For example, in `FancyInput.svelte`:
```svelte
```
- Do **NOT** overuse bindable props; instead, default to one-way data flow unless bi-directionality is truly needed.
_In Svelte 4, all props were implicitly bindable; in Svelte 5 `$bindable` makes this explicit._
### $host
- Only available inside custom elements. Access the host element for custom event dispatching. For example:
```svelte
```
- Do **NOT** use this unless you are explicitly tasked to create a custom element using Svelte components
### {#snippet ...}
- **Definition & Usage:**
Snippets allow you to define reusable chunks of markup with parameters inside your component.
_Example:_
```svelte
{#snippet figure(image)}
{image.caption}
{/snippet}
```
- **Parameterization:**
Snippets accept multiple parameters with optional defaults and destructuring, but rest parameters are not allowed.
_Example with parameters:_
```svelte
{#snippet name(param1, param2)}
{/snippet}
```
### Snippet scope
- **Lexical Visibility:**
Snippets can be declared anywhere and reference variables from their outer lexical scope, including script or block-level declarations.
_Example:_
```svelte
{#snippet hello(name)}
hello {name}! {message}!
{/snippet}
{@render hello('alice')}
```
- **Scope Limitations:**
Snippets are only accessible within their lexical scope; siblings and child blocks share scope, but nested snippets cannot be rendered outside.
_Usage caution:_ Do **NOT** attempt to render a snippet outside its declared scope.
### Passing snippets to components
- **As Props:**
Within a template, snippets are first-class values that can be passed to components as props.
_Example:_
```svelte
{#snippet header()}
fruit
qty
price
total
{/snippet}
{#snippet row(d)}
{d.name}
{d.qty}
{d.price}
{d.qty * d.price}
{/snippet}
```
- **Slot-like Behavior:**
Snippets declared inside component tags become implicit props (akin to slots) for the component.
_Svelte 4 used slots for this, e.g. `
hi {y}
`; now use snippets instead, e.g. `{#snippet x(y)}
hi {y}
{/snippet}`._
- **Content Fallback:**
Content not wrapped in a snippet declaration becomes the `children` snippet, rendering as fallback content.
_Example:_
```svelte
```
### Typing snippets
- Snippets implement the `Snippet` interface, enabling strict type checking in TypeScript or JSDoc.
_Example:_
```svelte
```
### {@render ...}
- Use the {@render ...} tag to invoke and render a snippet, passing parameters as needed.
_Example:_
```svelte
{#snippet sum(a, b)}
{a} + {b} = {a + b}
{/snippet}
{@render sum(1, 2)}
```
- Do **NOT** call snippets without parentheses when parameters are required; instead, always invoke the snippet correctly.
_In Svelte 4, you used slots for this, e.g. ``; now use `{@render}` instead, e.g. `{@render sum(a,b)}`._
###
- Use error boundary tags to prevent rendering errors in a section from crashing the whole app.
_Example:_
```svelte
console.error(error)}>
```
- **Failed Snippet for Fallback UI:**
Providing a `failed` snippet renders fallback content when an error occurs and supplies a `reset` function.
_Example:_
```svelte
{#snippet failed(error, reset)}
{/snippet}
```
### class
- Svelte 5 allows objects for conditional class assignment using truthy keys. It closely follows the `clsx` syntax
_Example:_
```svelte
Content
```
# SvelteKit documentation
## Project types
SvelteKit supports all rendering modes: SPA, SSR, SSG, and you can mix them within one project.
## Setup
Scaffold a new SvelteKit project using `npx sv create` then follow the instructions. Do NOT use `npm create svelte` anymore, this command is deprecated.
A SvelteKit project needs a `package.json` with the following contents at minimum:
```json
{
"devDependencies": {
"@sveltejs/adapter-auto": "^6.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"svelte": "^5.0.0",
"vite": "^6.0.0"
}
}
```
Do NOT put any of the `devDependencies` listed above into `dependencies`, keep them all in `devDependencies`.
It also needs a `vite.config.js` with the following at minimum:
```js
import { defineConfig } from 'vite';
import { sveltekit } from '@sveltejs/kit/vite';
export default defineConfig({
plugins: [sveltekit()]
});
```
It also needs a `svelte.config.js` with the following at minimum:
```js
import adapter from '@sveltejs/adapter-auto';
export default {
kit: {
adapter: adapter()
}
};
```
## Project structure
- **`src/` directory:**
- `lib/` for shared code (`$lib`), `lib/server/` for server‑only modules (`$lib/server`), `params/` for matchers, `routes/` for your pages/components, plus `app.html`, `error.html`, `hooks.client.js`, `hooks.server.js`, and `service-worker.js`.
- Do **NOT** import server‑only code into client files
- **Top‑level assets & configs:**
- `static/` for public assets; `tests/` (if using Playwright); config files: `package.json` (with `@sveltejs/kit`, `svelte`, `vite` as devDeps), `svelte.config.js`, `tsconfig.json` (or `jsconfig.json`, extending `.svelte-kit/tsconfig.json`), and `vite.config.js`.
- Do **NOT** forget `"type": "module"` in `package.json` if using ESM.
- **Build artifacts:**
- `.svelte-kit/` is auto‑generated and safe to ignore or delete; it will be recreated on `dev`/`build`.
- Do **NOT** commit `.svelte-kit/` to version control.
## Web standards
- **Fetch API & HTTP primitives:**
- Use `fetch` on server/routes/hooks and in the browser (`Request`, `Response`, `Headers`), plus `json()` helper.
- Do **NOT** roll your own HTTP parsing; instead use the platform’s `fetch` and `Request`/`Response` interfaces.
- **FormData & Streams:**
- Handle form submissions with `await event.request.formData()`, and stream large or chunked responses with `ReadableStream`/`WritableStream`/`TransformStream`.
- Do **NOT** load huge payloads into memory entirely; instead use streams when appropriate.
- **URL APIs & Web Crypto:**
- Access `event.url` or `page.url`, use `url.searchParams` for queries, and generate secure values with `crypto.randomUUID()`.
- Do **NOT** manually parse query strings or roll your own UUIDs; instead rely on `URLSearchParams` and the Web Crypto API.
## Routing
- **Filesystem router:** `src/routes` maps directories to URL paths: Everything with a `+page.svelte` file inside it becomes a visitable URL, e.g. `src/routes/hello/+page.svelte` becomes `/hello`. `[param]` folders define dynamic segments. Do NOT use other file system router conventions, e.g. `src/routes/hello.svelte` does NOT become available als URL `/hello`
- **Route files:** Prefix with `+`: all run server‑side; only non‑`+server` run client‑side; `+layout`/`+error` apply recursively.
- **Best practice:** Do **not** hard‑code routes in code; instead rely on the filesystem convention.
### +page.svelte
- Defines UI for a route, SSR on first load and CSR thereafter
- Do **not** fetch data inside the component; instead use a `+page.js` or `+page.server.js` `load` function; access its return value through `data` prop via `let { data } = $props()` (typed with `PageProps`).
```svelte
{data.title}
```
### +page.js
- Load data for pages via `export function load({ params })` (typed `PageLoad`), return value is put into `data` prop in component
- Can export `prerender`, `ssr`, and `csr` consts here to influence how page is rendered.
- Do **not** include private logic (DB or env vars); if needed, use `+page.server.js`.
```js
import type { PageLoad } from './$types';
export const load: PageLoad = () => {
return {
title: 'Hello world!',
};
}
```
### +page.server.js
- `export async function load(...)` (typed `PageServerLoad`) to access databases or private env; return serializable data.
- Can also export `actions` for `
```
### Validation errors
- Return `fail(400, { field, error: true })` from an action to send back status and data; display via `form?.field` and repopulate inputs with `value={form?.field ?? ''}`.
- Use `fail` instead of throwing so the nearest `+error.svelte` isn’t invoked and the user can correct their input.
- `fail` payload must be JSON‑serializable.
### Redirects
- In an action, call `redirect(status, location)` to send a 3xx redirect; this throws and bypasses form re-render.
- Client-side, use `goto()` from `$app/navigation` for programmatic redirects.
### Loading data after actions
- After an action completes (unless redirected), SvelteKit reruns `load` functions and re‑renders the page, merging the action’s return value into `form`.
- The `handle` hook runs once before the action; if you modify cookies in your action, you must also update `event.locals` there to keep `load` in sync.
- Do NOT assume `locals` persists automatically; set `event.locals` inside your action when auth state changes.
### Progressive enhancement
- Apply `use:enhance` from `$app/forms` to `
```
### Alternatives & GET vs POST
- For simple JSON APIs, use `+server.js` routes and `fetch` instead of actions; but you lose `