## docs/svelte/01-introduction/01-overview.md # Svelte Overview Svelte is a UI framework that compiles components into optimized JavaScript. Use it for anything from standalone components to full stack apps with SvelteKit. ```svelte ``` For beginners, start with the [interactive tutorial](/tutorial). Try Svelte online in the [playground](/playground) or on [StackBlitz](https://sveltekit.new). ## docs/svelte/01-introduction/02-getting-started.md # Getting Started with Svelte 5 ## Quick Start ```bash npx sv create myapp cd myapp npm install npm run dev ``` SvelteKit is the recommended framework for most projects. Alternatively: ```bash npm create vite@latest # Select svelte option ``` ## Editor Support - [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) - Command line: `sv check` ## Help Resources - [Discord](/chat) - [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte) ## docs/svelte/01-introduction/03-svelte-files.md # Svelte Components (.svelte files) Components are written in `.svelte` files with three optional sections: ```svelte ``` ## ` ``` You can `export` bindings from this block (except `export default`). ## ` ``` ## docs/svelte/01-introduction/04-svelte-js-files.md # .svelte.js and .svelte.ts files Svelte 5 operates on `.svelte.js` and `.svelte.ts` files in addition to `.svelte` files. These files: - Behave like regular JS/TS modules - Support runes for reactive logic - Allow sharing reactive state across your app ```js // store.svelte.js export let $state count = 0; export const increment = () => count += 1; ``` > Note: You cannot export reassigned state across modules. ## docs/svelte/02-runes/01-what-are-runes.md # Svelte 5 Runes Runes are compiler-controlled symbols in `.svelte` and `.svelte.js`/`.svelte.ts` files with a `$` prefix. ## Key Characteristics - No imports needed - built into Svelte - Not assignable to variables or passable as arguments - Only valid in specific positions (compiler will warn) - Always prefixed with `$` ```js let message = $state('hello'); ``` > Runes are new in Svelte 5 and replace the reactive syntax from previous versions. ## docs/svelte/02-runes/02-$state.md # Svelte 5 Runes - Condensed Documentation ## $state Creates reactive state that triggers UI updates when changed. ```svelte ``` ### Deep state Arrays and objects become deeply reactive state proxies: ```svelte ``` - Modifying nested properties triggers UI updates - New objects added to arrays are automatically proxified - Destructuring breaks reactivity ### Classes Use $state in class fields: ```js class Todo { done = $state(false); text = $state(); constructor(text) { this.text = text; } reset() { this.text = ''; this.done = false; } } ``` When using methods, handle `this` context: ```svelte ``` Or use arrow functions in class: ```js class Todo { // ... reset = () => { this.text = ''; this.done = false; } } ``` ## $state.raw For non-deeply reactive state: ```js let person = $state.raw({ name: 'Heraclitus', age: 49 }); // No effect person.age += 1; // Works - creates new object person = { name: 'Heraclitus', age: 50 }; ``` ## $state.snapshot Create static copy of reactive state: ```svelte ``` ## Passing state State is passed by value, not by reference: ```js let a = $state(1); let b = $state(2); // Accessing current values ``` For reactive objects: ```js function add(input) { return { get value() { return input.a + input.b; } }; } let input = $state({ a: 1, b: 2 }); let total = add(input); ``` ## Cross-module state Can't export directly reassigned state: ```js // Not allowed export let count = $state(0); export function increment() { count += 1; } ``` Instead, export objects: ```js // Allowed - updating property, not reassigning export const counter = $state({ count: 0 }); export function increment() { counter.count += 1; } ``` Or use getter functions: ```js let count = $state(0); export function getCount() { return count; } export function increment() { count += 1; } ``` ## docs/svelte/02-runes/03-$derived.md # $derived Rune in Svelte 5 The `$derived` rune creates reactive values that automatically update when their dependencies change. ## Basic Usage ```svelte
{count} doubled is {doubled}
``` > Without `$derived`, `doubled` would not update when `count` changes. ## Complex Derivations with $derived.by For multi-line derivations, use `$derived.by`: ```svelte ``` `$derived(expression)` is equivalent to `$derived.by(() => expression)`. ## Dependencies Any state read synchronously inside the `$derived` expression becomes a dependency. Use `untrack` to exempt state from being a dependency. ## Overriding Derived Values You can temporarily override derived values by reassigning them (useful for optimistic UI): ```svelte ``` ## Reactivity Behavior Unlike `$state`, `$derived` values are not converted to deeply reactive proxies. When accessing properties of a derived object that references a reactive state, mutations affect the underlying state. ## Update Propagation Svelte uses push-pull reactivity: - Changes are immediately pushed to dependents - Derived values are only recalculated when read - Updates are skipped if the new value is referentially identical to the previous value ```svelte ``` The button text only updates when `large` changes value, not on every `count` change. ## docs/svelte/02-runes/04-$effect.md # Svelte 5 $effect Rune ## Basic Usage Effects run when state updates, useful for third-party libraries, canvas manipulation, or network requests. They only run in the browser. ```svelte ``` ## Lifecycle - Effects run after DOM mounting and in a microtask after state changes - Re-runs are batched and happen after DOM updates - Can return a teardown function that runs before effect re-runs or when destroyed ```svelte{state.value} doubled is {derived.value}
``` ## Variants ### `$effect.pre` Runs before DOM updates: ```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(); ``` ## When Not To Use `$effect` Avoid using for state synchronization. Instead of: ```svelte ``` Use `$derived`: ```svelte ``` For linked values, use function bindings instead of effects: ```svelte ``` ## docs/svelte/02-runes/05-$props.md # $props in Svelte 5 The `$props` rune defines component inputs. ## Basic Usage ```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(); ``` ## Key Points - Props normally flow one-way (parent to child) - `$bindable` allows data to flow up from child to parent - Parent components can choose whether to use `bind:` or not - Use sparingly to maintain clear data flow in your app - State proxies can be mutated in child components ## docs/svelte/02-runes/07-$inspect.md # Svelte 5 Documentation: $inspect ## Basic Usage ```svelte ``` > **Note**: `$inspect` only works during development. In production, it becomes a no-op. ## $inspect(...).with Customize logging behavior with a callback: ```svelte ``` Quick trace shorthand: ```js $inspect(stuff).with(console.trace); ``` ## $inspect.trace(...) Traces reactive dependencies in development: ```svelte ``` Accepts an optional label parameter. ## docs/svelte/02-runes/08-$host.md # $host When compiling a component as a custom element, the `$host` rune provides access to the host element. ```svelte /// file: Stepper.sveltecount: {count}
``` ## docs/svelte/03-template-syntax/01-basic-markup.md # Basic Markup in Svelte 5 ## 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. Non-Promise expressions only render the `:then` branch. **Simplified variants:** ```svelte {#await promise}waiting for the promise to resolve...
{:then value}The value is {value}
{/await} ``` ```svelte {#await promise then value}The value is {value}
{/await} ``` ```svelte {#await promise catch error}The error is {error}
{/await} ``` > Use with dynamic imports for lazy loading: > ```svelte > {#await import('./Component.svelte') then { default: Component }} >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 into your component: ```svelteContent
fades in and out only when y changes
fades in and out when x or y change
{/if} {/if} ``` ## Parameters ```svelte {#if visible}The quick brown fox jumps over the lazy dog
{/if} ``` ## Transition Events Elements with transitions dispatch these events: - `introstart` - `introend` - `outrostart` - `outroend` ```svelte {#if visible}(status = 'intro started')} onoutrostart={() => (status = 'outro started')} onintroend={() => (status = 'intro ended')} onoutroend={() => (status = 'outro ended')} > Flies in and out
{/if} ``` ## docs/svelte/03-template-syntax/14-in-and-out.md # in: and out: Directives These directives create one-way transitions that don't reverse when interrupted. ```svelte {#if visible}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}{comment.content}
{/each} {:catch error}Error: {error.message}
{/await} ``` ## Rerunning Load Functions Load functions rerun when: - Referenced `params` or `url` properties change - Parent load function reruns (if using `await parent()`) - Manually invalidated with `invalidate()` or `invalidateAll()` ### Manual Invalidation ```js /** @type {import('./$types').PageLoad} */ export async function load({ fetch, depends }) { depends('app:random'); const response = await fetch('https://api.example.com/random-number'); return { number: await response.json() }; } ``` ```svelte ``` ## Using getRequestEvent Access request event in shared server code: ```js // src/lib/server/auth.js import { redirect } from '@sveltejs/kit'; import { getRequestEvent } from '$app/server'; export function requireLogin() { const { locals, url } = getRequestEvent(); if (!locals.user) { redirect(307, `/login?${new URLSearchParams({ redirectTo: url.pathname + url.search })}`); } return locals.user; } ``` ## docs/kit/20-core-concepts/30-form-actions.md # Svelte Form Actions ## Default Actions Define a default action in `+page.server.js`: ```js /// file: src/routes/login/+page.server.js export const actions = { default: async (event) => { // TODO log the user in } }; ``` Use it with a simple form: ```svelte ``` Target actions from other pages: ```html ``` ## Named Actions Multiple actions in one page: ```js export const actions = { login: async (event) => { // TODO log the user in }, register: async (event) => { // TODO register the user } }; ``` Invoke with query parameter: ```svelte ``` ## Action Anatomy Actions receive a `RequestEvent` and can return data: ```js import * as db from '$lib/server/db'; export const actions = { login: async ({ cookies, request }) => { const data = await request.formData(); const email = data.get('email'); const password = data.get('password'); const user = await db.getUser(email); cookies.set('sessionid', await db.createSession(user), { path: '/' }); return { success: true }; } }; ``` Access returned data in the page: ```svelte {#if form?.success}Successfully logged in! Welcome back, {data.user.name}
{/if} ``` ### Validation Errors Return validation errors with the `fail` function: ```js import { fail } from '@sveltejs/kit'; export const actions = { login: async ({ cookies, request }) => { const data = await request.formData(); const email = data.get('email'); const password = data.get('password'); if (!email) { return fail(400, { email, missing: true }); } const user = await db.getUser(email); if (!user || user.password !== db.hash(password)) { return fail(400, { email, incorrect: true }); } // Success case } }; ``` Display errors in the form: ```svelte ``` ### Redirects Redirect after an action: ```js import { fail, redirect } from '@sveltejs/kit'; export const actions = { login: async ({ cookies, request, url }) => { // Authentication logic if (url.searchParams.has('redirectTo')) { redirect(303, url.searchParams.get('redirectTo')); } return { success: true }; } }; ``` ## Loading Data After an action runs, the page's `load` functions run again. Update `event.locals` when setting cookies: ```js // In action event.cookies.delete('sessionid', { path: '/' }); event.locals.user = null; ``` ## Progressive Enhancement ### use:enhance Basic enhancement: ```svelte ``` To target actions in `+page.server.js` explicitly: ```js const response = await fetch(this.action, { method: 'POST', body: data, headers: { 'x-sveltekit-action': 'true' } }); ``` ## GET vs POST For non-data-modifying forms, use `method="GET"`: ```html ``` This navigates to `/search?q=...` using client-side routing without invoking an action. ## docs/kit/20-core-concepts/40-page-options.md # Svelte 5 Page Options ## Core Concepts ### Rendering Modes SvelteKit supports three rendering strategies: - **Server-Side Rendering (SSR)**: Default mode - renders on server first, then hydrates in browser - **Client-Side Rendering (CSR)**: Interactive components rendered in browser - **Prerendering**: Generate static HTML at build time Options can be set in `+page.js`, `+page.server.js`, `+layout.js`, or `+layout.server.js`. Child layouts/pages override parent settings. ## Page Options ### prerender ```js // Static generation at build time export const prerender = true; // Enable prerendering for this route export const prerender = false; // Disable prerendering export const prerender = 'auto'; // Prerender but keep in SSR manifest ``` **Notes:** - Prerendering crawls your app starting from the root - Routes with `prerender = true` are excluded from SSR manifests - For fully static sites, use `adapter-static` - During prerendering, `building` from `$app/environment` is `true` **When not to prerender:** - When users need different content (authentication, personalization) - Pages with form actions - Pages that access `url.searchParams` during prerendering **Route conflicts:** - Use file extensions for server routes (`foo.json` instead of `foo`) - Pages are written as `foo/index.html` instead of `foo` ### entries For dynamic routes that should be prerendered: ```js // src/routes/blog/[slug]/+page.server.js export function entries() { return [ { slug: 'hello-world' }, { slug: 'another-blog-post' } ]; } export const prerender = true; ``` Can be async to fetch data from CMS/database. ### ssr ```js export const ssr = false; // Disable server-side rendering ``` Renders empty shell page instead of full HTML. Useful for browser-only code but generally not recommended. ### csr ```js export const csr = false; // Disable client-side rendering ``` When disabled: - No JavaScript is sent to client - Page works with HTML/CSS only - No form progressive enhancement - Links cause full-page navigation - HMR is disabled For development-only CSR: ```js import { dev } from '$app/environment'; export const csr = dev; ``` ### trailingSlash ```js export const trailingSlash = 'never'; // Default - redirects /about/ to /about export const trailingSlash = 'always'; // Redirects /about to /about/ export const trailingSlash = 'ignore'; // Treats both forms as valid ``` Affects prerendering output: `always` creates `about/index.html`, otherwise creates `about.html`. ### config Platform-specific configuration for adapters: ```js /** @type {import('some-adapter').Config} */ export const config = { runtime: 'edge' }; ``` Config objects merge at top level but not deeper levels. ## docs/kit/20-core-concepts/50-state-management.md # Svelte 5 State Management ## Server State Guidelines ### Avoid Shared State on Server Servers are stateless and shared by multiple users. Never store user data in shared variables: ```js // NEVER DO THIS - shared variable exposes data between users let user; export function load() { return { user }; } export const actions = { default: async ({ request }) => { const data = await request.formData(); user = { name: data.get('name') }; // BAD: shared between users } } ``` Instead, authenticate users with cookies and store data in databases. ### No Side-Effects in Load Load functions should be pure: ```js // NEVER DO THIS - modifies global state import { user } from '$lib/user'; export async function load({ fetch }) { const response = await fetch('/api/user'); user.set(await response.json()); // BAD: affects all users } ``` Instead, return the data: ```js export async function load({ fetch }) { const response = await fetch('/api/user'); return { user: await response.json() }; } ``` ## Using Context for State Use Svelte's context API for component-scoped state: ```svelte ``` ```svelteWelcome {user().name}
``` ## Component State Preservation Components are reused during navigation. Reactive values must be properly declared: ```svelte ``` Correct approach: ```svelte ``` To force component remounting on navigation: ```svelte {#key page.url.pathname}Status: %sveltekit.status%
Message: %sveltekit.error.message%
``` ## Type Safety Customize error shape in TypeScript: ```ts declare global { namespace App { interface Error { code: string; id: string; } } } export {}; ``` ## docs/kit/30-advanced/30-link-options.md # SvelteKit Link Options ## Navigation Basics SvelteKit uses standard `` elements for navigation between routes. When clicking a link within your app, SvelteKit: - Imports the code for the new page - Calls necessary `load` functions - Updates the UI without a full page reload ## data-sveltekit-preload-data Controls when data loading begins: ```html