## docs/svelte/01-introduction/01-overview.md # Svelte Overview Svelte is a UI framework that compiles components into optimized JavaScript. Use it for standalone components or full-stack apps with SvelteKit. ```svelte ``` Try Svelte in the [interactive tutorial](/tutorial), [playground](/playground), or [StackBlitz](https://sveltekit.new). ## docs/svelte/01-introduction/02-getting-started.md # Getting Started with Svelte 5 ## Quick Start ```bash npx sv create myapp cd myapp npm install npm run dev ``` SvelteKit is the recommended framework for most projects. Alternatively: ```bash npm create vite@latest # Select svelte option ``` ## Editor Support - [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) - Command line: `sv check` ## Help Resources - [Discord](/chat) - [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte) ## docs/svelte/01-introduction/03-svelte-files.md # Svelte Files ## ` ``` ## ` ``` ## ` ``` All three sections (script, styles, markup) are optional. ## docs/svelte/01-introduction/04-svelte-js-files.md # .svelte.js and .svelte.ts files Svelte 5 operates on `.svelte.js` and `.svelte.ts` files in addition to `.svelte` files. These files: - Behave like regular JS/TS modules - Support runes for reactive logic - Allow sharing reactive state across your app ```js // store.svelte.js export let $state count = 0; export const increment = () => count += 1; ``` > Note: You cannot export reassigned state across modules. ## docs/svelte/02-runes/01-what-are-runes.md # Svelte 5 Runes Runes are compiler-controlled symbols in `.svelte` and `.svelte.js`/`.svelte.ts` files with a `$` prefix. ```js let message = $state('hello'); ``` Key characteristics: - No imports needed - Not assignable to variables or passable as arguments - Only valid in specific positions - Introduced in Svelte 5 ## docs/svelte/02-runes/02-$state.md # Svelte 5 Runes - Condensed Documentation ## $state Creates reactive state that triggers UI updates when changed. ```svelte ``` ### Deep state Arrays and objects become deeply reactive state proxies: ```svelte ``` - Modifying nested properties triggers UI updates - New objects added to arrays are automatically proxified - Destructuring breaks reactivity ### Classes Use $state in class fields: ```js class Todo { done = $state(false); text = $state(); constructor(text) { this.text = text; } reset() { this.text = ''; this.done = false; } } ``` When using methods, handle `this` context: ```svelte ``` Or use arrow functions in class: ```js reset = () => { this.text = ''; this.done = false; } ``` ## $state.raw For non-deeply reactive state: ```js let person = $state.raw({ name: 'Heraclitus', age: 49 }); // No effect person.age += 1; // Works - creates new object person = { name: 'Heraclitus', age: 50 }; ``` ## $state.snapshot Create static copy of reactive state: ```svelte ``` ## Passing state State is passed by value, not by reference: ```js function add(a, b) { return a + b; } let a = $state(1); let b = $state(2); let total = add(a, b); // total = 3 a = 3; // total still 3 ``` ## Cross-module state Can't export directly reassigned state: ```js // Not allowed export let count = $state(0); export function increment() { count += 1; } ``` Instead, either: 1. Export object with properties: ```js export const counter = $state({ count: 0 }); export function increment() { counter.count += 1; } ``` 2. Export getter functions: ```js let count = $state(0); export function getCount() { return count; } export function increment() { count += 1; } ``` ## docs/svelte/02-runes/03-$derived.md # $derived Rune The `$derived` rune creates reactive values that update when their dependencies change. ## Basic Usage ```svelte
{count} doubled is {doubled}
``` ## $derived.by For complex derivations, use `$derived.by` with a function: ```svelte ``` ## Dependencies Dependencies are automatically tracked when read synchronously inside the `$derived` expression. Use `untrack` to exclude dependencies. ## Overriding Derived Values You can temporarily override derived values by reassignment: ```svelte ``` ## Reactivity Behavior - Unlike `$state`, `$derived` values are not deeply reactive proxies - When accessing a property from reactive state, mutations to that property affect the underlying state: ```svelte let items = $state([...]); let index = $state(0); let selected = $derived(items[index]); ``` ## Update Propagation Svelte uses push-pull reactivity: - Changes are immediately pushed to dependents - Derived values are only recalculated when read - Updates are skipped if the new value is referentially identical to the previous value ```svelte ``` ## docs/svelte/02-runes/04-$effect.md # Svelte 5 $effect Rune ## Basic Usage Effects run when state updates, useful for third-party libraries, canvas manipulation, or network requests. They only run in the browser. ```svelte ``` ## Lifecycle - Effects run after DOM mounting and in a microtask after state changes - Re-runs are batched and happen after DOM updates - Can return a teardown function that runs before effect re-runs or when destroyed ```svelte{message}
{/each}in template: {$effect.tracking()}
``` ### `$effect.root` Creates a non-tracked scope without auto-cleanup: ```js const destroy = $effect.root(() => { $effect(() => { // setup }); return () => { // cleanup }; }); // later... destroy(); ``` ## Best Practices Avoid using `$effect` for state synchronization. Instead of: ```svelte ``` Use `$derived`: ```svelte ``` For linked values, use function bindings instead of effects: ```svelte ``` ## docs/svelte/02-runes/05-$props.md # $props in Svelte 5 The `$props` rune defines component inputs. ## Basic Usage ```sveltethis component is {adjective}
``` ## Fallback Values ```js let { adjective = 'happy' } = $props(); ``` > Note: Fallback values are not reactive state proxies ## Renaming Props ```js let { super: trouper = 'lights are gonna find me' } = $props(); ``` ## Rest Props ```js let { a, b, c, ...others } = $props(); ``` ## Updating Props Props update when parent values change. Child components can temporarily override prop values: ```svelte{message}
``` ## Default Values Provide fallback values when no prop is passed: ```js /// file: FancyInput.svelte let { value = $bindable('fallback'), ...props } = $props(); ``` ## Notes - Use sparingly - props typically flow one way (parent to child) - Without `bind:` in parent, behaves like a normal prop - Allows child components to mutate parent state ## docs/svelte/02-runes/07-$inspect.md # Svelte 5 Documentation: $inspect ## Basic Usage ```svelte ``` > **Note**: `$inspect` only works during development. In production, it becomes a no-op. ## $inspect(...).with Customize logging behavior with a callback: ```svelte ``` Quick trace shorthand: ```js $inspect(stuff).with(console.trace); ``` ## $inspect.trace(...) Traces reactive dependencies in development: ```svelte ``` Optional label parameter available. ## docs/svelte/02-runes/08-$host.md # $host When compiling a component as a custom element, the `$host` rune provides access to the host element. ```svelte /// file: Stepper.sveltecount: {count}
``` ## docs/svelte/03-template-syntax/01-basic-markup.md # Svelte 5 Basic Markup ## Tags ```svelte{a} + {b} = {a + b}.
what was the question?
{/if} ``` Chain conditions with `{:else if}` and `{:else}`: ```svelte {#if porridge.temperature > 100}too hot!
{:else if 80 > porridge.temperature}too cold!
{:else}just right!
{/if} ``` Note: Blocks can wrap elements or text within elements. ## docs/svelte/03-template-syntax/03-each.md # Svelte 5 Each Blocks ## Basic Usage ```svelte {#each expression as name}...{/each} {#each expression as name, index}...{/each} ``` Iterate over arrays, array-likes, or iterables (Map, Set, etc.): ```svelte{todo.text}
{:else}No tasks today!
{/each} ``` ## docs/svelte/03-template-syntax/04-key.md # {#key ...} ```svelte {#key expression}...{/key} ``` Key blocks destroy and recreate their contents when an expression value changes: ```svelte {#key value}waiting for the promise to resolve...
{:then value}The value is {value}
{:catch error}Something went wrong: {error.message}
{/await} ``` > During SSR, only the pending branch renders. If expression isn't a Promise, only `:then` branch renders. ## Simplified Variants Omit `:catch` when error handling isn't needed: ```svelte {#await promise}waiting for the promise to resolve...
{:then value}The value is {value}
{/await} ``` Omit pending state: ```svelte {#await promise then value}The value is {value}
{/await} ``` Show only error state: ```svelte {#await promise catch error}The error is {error}
{/await} ``` > You can use `#await` for lazy component loading: > ```svelte > {#await import('./Component.svelte') then { default: Component }} >hello {name}! {message}!
{/snippet} {@render hello('alice')} {@render hello('bob')} ``` Snippets are visible to siblings and their children. They can reference themselves and other snippets: ```svelte {#snippet countdown(n)} {#if n > 0} {n}... {@render countdown(n - 1)} {:else} {@render blastoff()} {/if} {/snippet} {#snippet blastoff()} ๐ {/snippet} {@render countdown(10)} ``` ## Passing Snippets to Components ### Explicit Props ```svelte {#snippet header()}fruit | qty | price | total | {/snippet} {#snippet row(d)}{d.name} | {d.qty} | {d.price} | {d.qty * d.price} | {/snippet}
---|
{a} + {b} = {a + b}
{/snippet} {@render sum(1, 2)} {@render sum(3, 4)} {@render sum(5, 6)} ``` The expression can be an identifier or any JavaScript expression: ```svelte {@render (cool ? coolSnippet : lameSnippet)()} ``` ## Optional snippets For potentially undefined snippets, use optional chaining: ```svelte {@render children?.()} ``` Or use an `{#if ...}` block with fallback content: ```svelte {#if children} {@render children()} {:else}fallback content
{/if} ``` ## docs/svelte/03-template-syntax/08-@html.md # {@html ...} Use `{@html ...}` to inject raw HTML: ```svelteContent
fades in and out only when y changes
fades in and out when x or y change
{/if} {/if} ``` ## Parameters Transitions can accept parameters: ```svelte {#if visible}The quick brown fox jumps over the lazy dog
{/if} ``` Custom transitions receive an `options` object with `direction` (`in`, `out`, or `both`). ## Events Transition elements dispatch these events: - `introstart` - `introend` - `outrostart` - `outroend` ```svelte {#if visible}(status = 'intro started')} onoutrostart={() => (status = 'outro started')} onintroend={() => (status = 'intro ended')} onoutroend={() => (status = 'outro ended')} > Flies in and out
{/if} ``` ## docs/svelte/03-template-syntax/14-in-and-out.md # in: and out: Directives These directives create unidirectional transitions, unlike bidirectional `transition:` directives. - `in:` transitions play when element enters - `out:` transitions play when element leaves - Both transitions run simultaneously during direction changes - Aborted transitions restart from scratch ```svelte {#if visible}User name: {userState.name}
``` Use stores for complex async data streams or when manual control over updates is needed. ## svelte/store API ### `writable` Creates a store with values that can be set externally. ```js import { writable } from 'svelte/store'; const count = writable(0); count.subscribe((value) => { console.log(value); }); // logs '0' count.set(1); // logs '1' count.update((n) => n + 1); // logs '2' ``` With start/stop functions: ```js import { writable } from 'svelte/store'; const count = writable(0, () => { console.log('got a subscriber'); return () => console.log('no more subscribers'); }); count.set(1); // does nothing const unsubscribe = count.subscribe((value) => { console.log(value); }); // logs 'got a subscriber', then '1' unsubscribe(); // logs 'no more subscribers' ``` ### `readable` Creates a store whose value cannot be set externally. ```ts import { readable } from 'svelte/store'; const time = readable(new Date(), (set) => { set(new Date()); const interval = setInterval(() => { set(new Date()); }, 1000); return () => clearInterval(interval); }); const ticktock = readable('tick', (set, update) => { const interval = setInterval(() => { update((sound) => (sound === 'tick' ? 'tock' : 'tick')); }, 1000); return () => clearInterval(interval); }); ``` ### `derived` Derives a store from one or more other stores. ```ts import { derived } from 'svelte/store'; const doubled = derived(a, ($a) => $a * 2); ``` Asynchronous derivation: ```ts import { derived } from 'svelte/store'; const delayed = derived( a, ($a, set) => { setTimeout(() => set($a), 1000); }, 2000 ); const delayedIncrement = derived(a, ($a, set, update) => { set($a); setTimeout(() => update((x) => x + 1), 1000); }); ``` With cleanup function: ```ts import { derived } from 'svelte/store'; const tick = derived( frequency, ($frequency, set) => { const interval = setInterval(() => { set(Date.now()); }, 1000 / $frequency); return () => { clearInterval(interval); }; }, 2000 ); ``` Multiple source stores: ```ts import { derived } from 'svelte/store'; const summed = derived([a, b], ([$a, $b]) => $a + $b); const delayed = derived([a, b], ([$a, $b], set) => { setTimeout(() => set($a + $b), 1000); }); ``` ### `readonly` Makes a store readonly. ```js import { readonly, writable } from 'svelte/store'; const writableStore = writable(1); const readableStore = readonly(writableStore); readableStore.subscribe(console.log); writableStore.set(2); // console: 2 // readableStore.set(2); // ERROR ``` ### `get` Retrieves the current value of a store without subscribing. ```ts import { get } from 'svelte/store'; const value = get(store); ``` ## Store Contract A valid store must: 1. Have a `.subscribe` method that accepts a subscription function 2. Call the subscription function immediately with the current value 3. Return an unsubscribe function 4. Optionally have a `.set` method (for writable stores) ## docs/svelte/06-runtime/02-context.md # Context Context allows components to access values from parent components without prop-drilling. ## Basic Usage ```svelte ``` ```svelte{message}
{/each}Next post: {next.title}
{/if} ``` ## Universal vs Server Load Functions **Server load functions** (`+page.server.js`, `+layout.server.js`): - Always run on the server - Can access database, filesystem, private env vars - Must return serializable data - Have access to `cookies`, `locals`, etc. **Universal load functions** (`+page.js`, `+layout.js`): - Run on server during SSR, then in browser - Useful for fetching from external APIs - Can return non-serializable data (like component constructors) - Receive data from server load functions via the `data` property ## Making Fetch Requests Use the provided `fetch` function for enhanced features: ```js // src/routes/items/[id]/+page.js export async function load({ fetch, params }) { const res = await fetch(`/api/items/${params.id}`); const item = await res.json(); return { item }; } ``` ## Headers and Cookies Set response headers: ```js export async function load({ fetch, setHeaders }) { const response = await fetch(url); setHeaders({ age: response.headers.get('age'), 'cache-control': response.headers.get('cache-control') }); return response.json(); } ``` Access cookies in server load functions: ```js export async function load({ cookies }) { const sessionid = cookies.get('sessionid'); return { user: await db.getUser(sessionid) }; } ``` ## Using Parent Data Access data from parent load functions: ```js export async function load({ parent }) { const { a } = await parent(); return { b: a + 1 }; } ``` ## Errors and Redirects Throw errors: ```js import { error } from '@sveltejs/kit'; export function load({ locals }) { if (!locals.user) { error(401, 'not logged in'); } } ``` Redirect users: ```js import { redirect } from '@sveltejs/kit'; export function load({ locals }) { if (!locals.user) { redirect(307, '/login'); } } ``` ## Streaming with Promises Server load functions can stream promises as they resolve: ```js export async function load({ params }) { return { comments: loadComments(params.slug), post: await loadPost(params.slug) }; } ``` ```svelte{comment.content}
{/each} {:catch error}error loading comments: {error.message}
{/await} ``` ## Rerunning Load Functions Load functions rerun when: - Referenced params or URL properties change - A parent load function reran and `await parent()` was called - A dependency was invalidated with `invalidate(url)` or `invalidateAll()` Manually invalidate load functions: ```js // In load function export async function load({ fetch, depends }) { depends('app:random'); // ... } // In component import { invalidate } from '$app/navigation'; function rerunLoadFunction() { invalidate('app:random'); } ``` ## Dependency Tracking Exclude from dependency tracking with `untrack`: ```js export async function load({ untrack, url }) { if (untrack(() => url.pathname === '/')) { return { message: 'Welcome!' }; } } ``` ## docs/kit/20-core-concepts/30-form-actions.md # Svelte Form Actions ## Default Actions Define a default action in `+page.server.js`: ```js /// file: src/routes/login/+page.server.js /** @satisfies {import('./$types').Actions} */ export const actions = { default: async (event) => { // TODO log the user in } }; ``` Use it with a simple form: ```svelte ``` From other pages, specify the action path: ```html ``` ## Named Actions Multiple actions in one page: ```js /// file: src/routes/login/+page.server.js /** @satisfies {import('./$types').Actions} */ export const actions = { login: async (event) => { // TODO log the user in }, register: async (event) => { // TODO register the user } }; ``` Invoke with query parameter: ```svelte ``` Use `formaction` for multiple actions in one form: ```svelte ``` > Note: Can't mix default and named actions ## Action Implementation ```js 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'); const user = await db.getUser(email); cookies.set('sessionid', await db.createSession(user), { path: '/' }); return { success: true }; } }; ``` Access returned data in component: ```svelte {#if form?.success}Successfully logged in! Welcome back, {data.user.name}
{/if} ``` ### Validation Errors Return errors with the `fail` function: ```js import { fail } from '@sveltejs/kit'; /** @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 }); } // Success case } }; ``` Handle errors in the component: ```svelte ``` ### Redirects ```js import { fail, redirect } from '@sveltejs/kit'; /** @satisfies {import('./$types').Actions} */ export const actions = { login: async ({ cookies, request, url }) => { // validation logic... if (url.searchParams.has('redirectTo')) { redirect(303, url.searchParams.get('redirectTo')); } return { success: true }; } }; ``` ## Loading Data After an action runs, the page's `load` functions run. If you modify cookies in an action, update `event.locals` too: ```js /// file: src/routes/account/+page.server.js /** @satisfies {import('./$types').Actions} */ export const actions = { logout: async (event) => { event.cookies.delete('sessionid', { path: '/' }); event.locals.user = null; } }; ``` ## Progressive Enhancement ### use:enhance Basic enhancement: ```svelte ``` Default behavior: - Updates `form` property and `page.form` (only for same-page actions) - Resets the form - Invalidates all data on success - Handles redirects and errors - Resets focus ### Customizing use:enhance ```svelte ``` To target `+page.server.js` actions with fetch: ```js const response = await fetch(this.action, { method: 'POST', body: data, headers: { 'x-sveltekit-action': 'true' } }); ``` ## GET Forms For forms that don't need to POST data: ```html ``` These navigate like `` elements and support the same data attributes for controlling router behavior. ## docs/kit/20-core-concepts/40-page-options.md # Svelte 5 Page Options ## Core Concepts ### Rendering Modes SvelteKit supports three rendering strategies: - **Server-Side Rendering (SSR)**: Default, renders on server first - **Client-Side Rendering (CSR)**: Hydrates server-rendered HTML - **Prerendering**: Generates static HTML at build time Options can be set in `+page.js`, `+page.server.js`, `+layout.js`, or `+layout.server.js`. Child pages override parent layouts. ## Page Options ### prerender Generate static HTML at build time: ```js /// file: +page.js/+page.server.js/+server.js export const prerender = true; // Enable for this route export const prerender = false; // Disable for this route export const prerender = 'auto'; // Prerender but keep in SSR manifest ``` **When to use prerendering**: - Content must be the same for all users - No need for `url.searchParams` during prerendering - Pages with [actions](form-actions) cannot be prerendered **Route conflicts**: Use file extensions for server routes to avoid conflicts: ``` src/routes/foo.json/+server.js // Creates foo.json src/routes/foo/bar.json/+server.js // Creates foo/bar.json ``` ### entries For dynamic routes that need prerendering: ```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; ``` ### ssr Disable server-side rendering: ```js /// file: +page.js export const ssr = false; // Creates empty shell page, renders only on client ``` ### csr Disable client-side rendering: ```js /// file: +page.js export const csr = false; // No JavaScript sent to client, links cause full page navigation ``` Enable CSR only during development: ```js /// file: +page.js import { dev } from '$app/environment'; export const csr = dev; ``` ### trailingSlash Control URL trailing slashes: ```js /// file: src/routes/+layout.js export const trailingSlash = 'always'; // '/about/' format // Options: 'never' (default), 'always', 'ignore' ``` ### config Platform-specific configuration for adapters: ```js /// file: src/routes/+page.js /** @type {import('some-adapter').Config} */ export const config = { runtime: 'edge' }; ``` Config objects merge at the top level but not deeper levels. ## Best Practices - Use prerendering for static content - Use SSR for dynamic, SEO-important pages - Use CSR-only (SPA mode) for admin sections - Avoid ignoring trailing slashes (harmful for SEO) - Keep browser-only code in component files, not in page option files ## docs/kit/20-core-concepts/50-state-management.md # Svelte 5 State Management ## Server State Guidelines ### Avoid Shared State on Server Servers are stateless and shared by multiple users. Never store user data in shared variables: ```js // NEVER DO THIS! let user; // Shared by all users export function load() { return { user }; } export const actions = { default: async ({ request }) => { const data = await request.formData(); user = { // BAD: exposes one user's data to others name: data.get('name'), secret: data.get('secret') }; } } ``` Instead, authenticate users with cookies and store data in databases. ### No Side-Effects in Load Load functions should be pure: ```js // NEVER DO THIS! import { user } from '$lib/user'; export async function load({ fetch }) { const response = await fetch('/api/user'); user.set(await response.json()); // BAD: shared state } ``` Instead, return the data: ```js export async function load({ fetch }) { const response = await fetch('/api/user'); return { user: await response.json() }; } ``` ## Using Context for State Use Svelte's context API for component tree state: ```svelte ``` ```svelteWelcome {user().name}
``` > Pass functions to `setContext` to maintain reactivity across boundaries. ## Component State Preservation SvelteKit reuses components during navigation. Make values reactive to handle updates: ```svelte ``` Correct approach: ```svelte ``` To force component remounting on navigation: ```svelte {#key page.url.pathname}Status: %sveltekit.status%
Message: %sveltekit.error.message%
``` ## Type Safety Customize error shape with TypeScript: ```ts declare global { namespace App { interface Error { code: string; id: string; } } } export {}; ``` ## docs/kit/30-advanced/30-link-options.md # Link Options in SvelteKit SvelteKit uses standard `` elements for navigation between routes. When clicking a link within your app, SvelteKit imports the code and calls necessary `load` functions to fetch data. ## data-sveltekit-preload-data Controls when data preloading begins: - `"hover"` - starts on mouse hover or mobile `touchstart` - `"tap"` - starts on `touchstart` or `mousedown` Default setup in `app.html`: ```html