# Svelte ## Introduction Svelte is a modern frontend framework that takes a fundamentally different approach to building user interfaces. Unlike traditional frameworks that do the bulk of their work in the browser, Svelte is a compiler that converts declarative component code into highly efficient imperative JavaScript that surgically updates the DOM. This compilation step eliminates the need for a virtual DOM and runtime overhead, resulting in smaller bundle sizes and faster performance. Components are written in `.svelte` files using an intuitive syntax that combines HTML, CSS, and JavaScript, making it accessible to web developers while providing powerful reactive primitives. As of version 5.45, Svelte continues to evolve with new features for reactivity, performance optimization, and developer experience. The Svelte ecosystem consists of multiple packages and tools that work together seamlessly. The core `svelte` package provides the component framework and compiler, while `svelte/store` offers state management utilities, `svelte/motion` handles animations, and `svelte/transition` provides built-in transition effects. Svelte 5 introduces runes—a new reactivity system using `$state`, `$derived`, and `$effect`—that offers fine-grained control over reactive behavior. The framework also includes `svelte/reactivity` with reactive data structures and window bindings, `svelte/events` for enhanced event handling, and `svelte/attachments` for modern DOM behavior patterns. A comprehensive compiler API enables parsing and transforming Svelte components, server-side rendering capabilities support universal applications, and integration with modern build tools ensures optimal development workflows. SvelteKit, the official application framework, builds on top of Svelte to provide routing, server-side rendering, and full-stack capabilities. ## APIs and Functions ### Component Mounting and Lifecycle **mount** - Mount a component to a DOM element ```javascript import { mount } from 'svelte'; import App from './App.svelte'; // Basic mounting const app = mount(App, { target: document.getElementById('app'), props: { name: 'World', count: 42 } }); // Advanced mounting with context and events const instance = mount(App, { target: document.body, anchor: document.querySelector('#insertion-point'), props: { user: { id: 1, name: 'Alice' } }, context: new Map([['theme', 'dark']]), intro: true, // Play transitions on mount (default: true) events: { // Deprecated: prefer callback props instead customEvent: (e) => console.log('Event:', e.detail) } }); // Access exported values from the component console.log(instance.someExportedFunction()); ``` **unmount** - Unmount a component instance ```javascript import { mount, unmount } from 'svelte'; import Modal from './Modal.svelte'; const modal = mount(Modal, { target: document.body, props: { title: 'Confirm Action' } }); // Unmount without playing outro transitions await unmount(modal); // Unmount with outro transitions (Svelte 5.13+) await unmount(modal, { outro: true }); ``` **hydrate** - Hydrate server-rendered HTML with a component ```javascript import { hydrate } from 'svelte'; import App from './App.svelte'; // Hydrate server-rendered content const app = hydrate(App, { target: document.getElementById('app'), props: { data: window.__INITIAL_DATA__ } }); // With recover mode (attempts to fix mismatches) const appWithRecovery = hydrate(App, { target: document.getElementById('app'), props: { data: window.__INITIAL_DATA__ }, recover: true // Default: true. Set false to strictly fail on mismatch }); ``` **onMount** - Run code when component mounts to DOM ```javascript ``` **onDestroy** - Run cleanup code when component unmounts ```javascript ``` **tick** - Wait for pending state changes to apply ```javascript
{count}
``` **settled** - Wait for all state changes and async work to complete ```javascript ``` **flushSync** - Synchronously apply pending state changes ```javascript ``` ### Context API **createContext** - Create type-safe context getter/setter pair ```javascript
Content
``` **setContext / getContext** - Share data between parent and child components ```javascript
Themed content
``` **hasContext** - Check if context exists ```javascript ``` **getAllContexts** - Retrieve all contexts from parent ```javascript ``` ### Reactivity and State Management **untrack** - Read state without creating dependencies ```javascript ``` **getAbortSignal** - Get signal that aborts when effect/derived re-runs ```javascript ``` **fork** - Create a fork for off-screen work (experimental) ```javascript import { fork } from 'svelte'; // Create a fork for preloading data without affecting the DOM async function preloadRoute(routeData) { const forked = fork(() => { // State changes here are evaluated but not applied to DOM someState = routeData; // Run effects and deriveds }); // Later, when the user navigates, commit the fork await forked.commit(); // Applies all state changes to DOM // Or discard if navigation was cancelled // forked.discard(); } // Example: Preload data on hover function handleHover(link) { const forked = fork(() => { // Fetch and process data in isolation fetchPageData(link.href); }); link.addEventListener('click', async () => { // Commit the preloaded state await forked.commit(); }); link.addEventListener('mouseleave', () => { // Discard if user doesn't click forked.discard(); }, { once: true }); } ``` **createSubscriber** - Integrate external event systems with reactivity ```javascript ``` ### Store APIs **writable** - Create a writable store ```javascript import { writable } from 'svelte/store'; // Simple store const count = writable(0); // Subscribe to changes const unsubscribe = count.subscribe(value => { console.log('Count:', value); }); // Update the value count.set(5); count.update(n => n + 1); unsubscribe(); // Store with start/stop logic const websocket = writable(null, (set, update) => { const ws = new WebSocket('wss://example.com/socket'); ws.addEventListener('message', (event) => { set(JSON.parse(event.data)); }); ws.addEventListener('open', () => { console.log('WebSocket connected'); }); // Cleanup function return () => { ws.close(); console.log('WebSocket disconnected'); }; }); // In Svelte components, use $ prefix for auto-subscription // //
{$count}
``` **readable** - Create a read-only store ```javascript import { readable } from 'svelte/store'; // Simple readable const time = readable(new Date(), (set) => { const interval = setInterval(() => { set(new Date()); }, 1000); return () => clearInterval(interval); }); // Geolocation store const location = readable(null, (set) => { if (!navigator.geolocation) { set({ error: 'Geolocation not supported' }); return; } const watchId = navigator.geolocation.watchPosition( (position) => { set({ latitude: position.coords.latitude, longitude: position.coords.longitude, accuracy: position.coords.accuracy }); }, (error) => set({ error: error.message }) ); return () => navigator.geolocation.clearWatch(watchId); }); ``` **derived** - Create a store derived from other stores ```javascript import { writable, derived } from 'svelte/store'; const firstName = writable('Alice'); const lastName = writable('Smith'); // Synchronous derived const fullName = derived( [firstName, lastName], ([$first, $last]) => `${$first} ${$last}` ); // Asynchronous derived with set callback const user = derived( fullName, ($fullName, set) => { fetch(`/api/users?name=${$fullName}`) .then(r => r.json()) .then(data => set(data)) .catch(err => set({ error: err.message })); // Optional: return cleanup return () => { console.log('Cleanup for', $fullName); }; }, { loading: true } // Initial value ); // Derived from single store const doubled = derived(count, $count => $count * 2); // Complex derived with multiple stores const cart = writable([ { id: 1, name: 'Item 1', price: 10, quantity: 2 }, { id: 2, name: 'Item 2', price: 15, quantity: 1 } ]); const taxRate = writable(0.08); const cartTotal = derived( [cart, taxRate], ([$cart, $taxRate]) => { const subtotal = $cart.reduce((sum, item) => sum + item.price * item.quantity, 0); const tax = subtotal * $taxRate; return { subtotal, tax, total: subtotal + tax }; } ); ``` **readonly** - Make a store read-only ```javascript import { writable, readonly } from 'svelte/store'; const _count = writable(0); // Export readonly version export const count = readonly(_count); // Export methods to modify the store export function increment() { _count.update(n => n + 1); } export function reset() { _count.set(0); } ``` **get** - Get current store value without subscribing ```javascript import { writable, get } from 'svelte/store'; const count = writable(5); // Get current value const currentCount = get(count); console.log(currentCount); // 5 // Warning: Creates temporary subscription // Don't use in reactive contexts (use $count instead) function handleClick() { const value = get(count); console.log('Clicked with count:', value); count.set(value + 1); } ``` **toStore / fromStore** - Bridge between runes and stores ```javascript import { toStore, fromStore } from 'svelte/store'; // Convert $state to store let count = $state(0); const countStore = toStore( () => count, (v) => count = v ); // Read-only version const readonlyStore = toStore(() => count); // Use in non-runes code countStore.subscribe(value => console.log('Count:', value)); // Convert store to runes-compatible object import { writable } from 'svelte/store'; const externalStore = writable(42); const runeState = fromStore(externalStore); $effect(() => { console.log('Value:', runeState.current); }); // For writable stores, you can set the value runeState.current = 100; // Updates the store ``` ### Reactive Data Structures **SvelteMap** - Reactive Map implementation ```javascript
Total users: {users.size}
{#each users as [id, user]}
{user.name} ({user.role})
{/each} ``` **SvelteSet** - Reactive Set implementation ```javascript
Tags: {tags.size}
{#each tags as tag} {tag} {/each} ``` **SvelteDate** - Reactive Date wrapper ```javascript

Current time: {now.toLocaleTimeString()}

Unix timestamp: {now.getTime()}

Date: {now.toLocaleDateString()}

``` **SvelteURL** - Reactive URL and URLSearchParams ```javascript

Full URL: {url.href}

Path: {url.pathname}

Query: {url.searchParams.get('q')}

Page: {url.searchParams.get('page')}

``` **SvelteURLSearchParams** - Reactive URLSearchParams wrapper ```javascript

Query string: {params.toString()}

Search: {params.get('q')}

Filters: {params.getAll('filter').join(', ')}

``` **MediaQuery** - Reactive media query matching ```javascript
{#if isDesktop.current} {:else} {/if}
Content
``` **Window Reactive Values** - Reactive window and navigator properties ```javascript

Window: {innerWidth.current}x{innerHeight.current}

Scroll: {scrollX.current}, {scrollY.current}

Status: {online.current ? 'Online' : 'Offline'}

{#if isMobile} {:else if isTablet} {:else} {/if}
Parallax content
``` ### Transitions and Animations **fade** - Fade in/out transition ```javascript {#if visible}
Fades in and out
t }}> Custom fade (1 second, linear)
{/if} ``` **fly** - Fly in from position ```javascript {#if show}
Flies in from left
Flies down from top
Flies with custom curve
{/if} ``` **slide** - Slide transition ```javascript {#if expanded}

This content slides in and out

Smoothly revealing more content

{/if} {#if expanded}
Slides horizontally
{/if} ``` **scale** - Scale transition ```javascript {#if showModal} {/if} ``` **flip** - FLIP animation for list reordering ```javascript ``` **crossfade** - Crossfade between two elements ```javascript

Todo

{#each todos.filter(t => !t.done) as todo (todo.id)}
toggle(todo.id)} /> {todo.text}
{/each}

Done

{#each todos.filter(t => t.done) as todo (todo.id)}
toggle(todo.id)} /> {todo.text}
{/each}
``` ### Motion and Springs **Spring** - Spring physics animation ```javascript
Progress: {Math.round(spring.current)}%
``` **tweened** - Tween animation between values ```javascript ``` **prefersReducedMotion** - Detect reduced motion preference ```javascript {#if visible}
Respects motion preferences
{/if} ``` ### Actions **use:action** - Attach behavior to DOM elements ```javascript Lazy loaded ``` ### Event Handling **on** - Programmatically attach event listeners ```javascript ``` ### Attachments **createAttachmentKey** - Create attachment keys programmatically ```javascript ``` **fromAction** - Convert actions to attachments ```javascript ``` ### Compiler API **compile** - Compile Svelte component to JavaScript ```javascript import { compile } from 'svelte/compiler'; import fs from 'fs'; const source = fs.readFileSync('App.svelte', 'utf-8'); const result = compile(source, { filename: 'App.svelte', name: 'App', generate: 'client', // 'client' | 'server' dev: false, css: 'injected', // 'injected' | 'external' | 'none' cssHash: ({ hash, css, name, filename }) => `svelte-${hash(css)}`, runes: true, // Enable runes (default in Svelte 5) warningFilter: (warning) => { // Ignore specific warnings return warning.code !== 'css-unused-selector'; } }); // Output console.log('JavaScript:', result.js.code); console.log('CSS:', result.css?.code); console.log('Warnings:', result.warnings); console.log('AST:', result.ast); // Write compiled output fs.writeFileSync('App.js', result.js.code); if (result.css) { fs.writeFileSync('App.css', result.css.code); } // Handle warnings result.warnings.forEach(warning => { console.warn(`${warning.filename}:${warning.start?.line} - ${warning.message}`); }); ``` **parse** - Parse Svelte component to AST ```javascript import { parse } from 'svelte/compiler'; const source = ` `; // Modern AST (Svelte 5+) const modernAst = parse(source, { modern: true }); console.log('Modern AST:', JSON.stringify(modernAst, null, 2)); // Legacy AST const legacyAst = parse(source, { modern: false }); console.log('Legacy AST:', legacyAst); // Loose parsing (tries to parse invalid code) const invalidSource = '
Unclosed'; const looseAst = parse(invalidSource, { modern: true, loose: true }); console.log('Parsed despite errors:', looseAst); ``` **preprocess** - Transform component source before compilation ```javascript import { preprocess } from 'svelte/compiler'; const source = `
`; const result = await preprocess(source, [ { // TypeScript preprocessor script: ({ content, attributes }) => { if (attributes.lang !== 'ts') return; // Use TypeScript compiler or esbuild const code = transformTypeScript(content); return { code }; } }, { // SCSS preprocessor style: async ({ content, attributes }) => { if (attributes.lang !== 'scss') return; const { css } = await compileSass(content); return { code: css }; } }, { // Markup preprocessor (e.g., add JSDoc comments) markup: ({ content }) => { const enhanced = content.replace( / {@render dynamicSnippet(() => userName)} {@render counter(() => count, () => count++)} ``` ### Easing Functions **Built-in easing functions** - Animation timing functions ```javascript import { linear, cubicOut, cubicInOut, quintOut, elasticOut, bounceOut } from 'svelte/easing'; import { tweened } from 'svelte/motion'; import { fly } from 'svelte/transition'; const linearValue = tweened(0, { easing: linear }); const smoothValue = tweened(0, { easing: cubicOut }); const elasticValue = tweened(0, { easing: elasticOut }); const bounceValue = tweened(0, { easing: bounceOut }); // Available easing functions: // linear, backIn, backOut, backInOut // bounceIn, bounceOut, bounceInOut // circIn, circOut, circInOut // cubicIn, cubicOut, cubicInOut // elasticIn, elasticOut, elasticInOut // expoIn, expoOut, expoInOut // quadIn, quadOut, quadInOut // quartIn, quartOut, quartInOut // quintIn, quintOut, quintInOut // sineIn, sineOut, sineInOut ``` ## Summary Svelte provides a comprehensive and modern approach to building reactive web applications through its compilation-based architecture. The framework's APIs are designed to be intuitive and ergonomic, reducing boilerplate while maintaining full type safety. Core runtime functions like `mount`, `hydrate`, and the lifecycle hooks (`onMount`, `onDestroy`) give developers fine-grained control over component behavior. The context API enables clean dependency injection patterns, while the reactivity system—powered by runes (`$state`, `$derived`, `$effect`)—provides automatic tracking of dependencies with options for optimization through `untrack` and `getAbortSignal`. Async utilities like `tick` and `settled` help coordinate DOM updates and state changes. The experimental `fork` API enables off-screen state evaluation for advanced use cases like route preloading. The store APIs (`writable`, `readable`, `derived`) offer robust state management that integrates seamlessly with the runes system via `toStore` and `fromStore` bridges. Beyond basic reactivity, Svelte includes a rich ecosystem of utilities for common frontend tasks. The reactive data structures (`SvelteMap`, `SvelteSet`, `SvelteDate`, `SvelteURL`, `SvelteURLSearchParams`) wrap built-in JavaScript objects with automatic change tracking. The `createSubscriber` API allows seamless integration of external event systems (WebSockets, IntersectionObserver, etc.) with Svelte's reactivity. Window properties (`scrollX`, `scrollY`, `innerWidth`, `innerHeight`, `online`, etc.) are available as reactive values through `svelte/reactivity/window`, making it trivial to build responsive and scroll-aware interfaces. Built-in transitions (`fade`, `fly`, `slide`, `scale`) and animations (`flip`, `crossfade`) make UI polish straightforward, while `Spring` and `tweened` enable physics-based and interpolated animations with minimal code. The action system (`use:action`) provides a powerful way to encapsulate reusable DOM behaviors, while the newer attachment API (`createAttachmentKey`, `fromAction`) offers a modern alternative for library authors. Event handling is enhanced with the `on` function that preserves proper event delegation ordering. On the tooling side, the compiler API (`compile`, `parse`, `preprocess`) enables custom build pipelines and editor integrations, while server-side rendering through the `render` function supports universal/isomorphic applications. This combination of compiler intelligence, reactive primitives, and practical utilities makes Svelte an excellent choice for projects ranging from simple widgets to complex full-stack applications.