# Svelte Administrator & Developer Guide

> **Version**: 5.55.4 | **Source commit**: `fcaa8ce` | **License**: MIT
>
> This guide covers the internal architecture, compiler pipeline, runtime internals, configuration, operations, and integration points for the Svelte framework. It is written for contributors, framework integrators, tooling authors, and advanced users who need to understand how Svelte works beneath the surface.

---

## Table of Contents

1. [Architecture Overview](#1-architecture-overview)
2. [System Requirements](#2-system-requirements)
3. [Configuration Reference](#3-configuration-reference)
4. [Deployment & Scaling](#4-deployment--scaling)
5. [Operations](#5-operations)
6. [Performance](#6-performance)
7. [Security](#7-security)
8. [Developer Internals](#8-developer-internals)
9. [Integration Points](#9-integration-points)

---

## 1. Architecture Overview

Svelte is a **compile-time web framework**. Unlike runtime frameworks (React, Vue), Svelte shifts the bulk of the framework work to a build step: components are compiled from `.svelte` source files into optimized JavaScript that directly manipulates the DOM with minimal runtime overhead.

The framework consists of two independent but cooperating systems:

| System | Role | Location |
|--------|------|----------|
| **Compiler** | Transforms `.svelte` → JS + CSS at build time | `packages/svelte/src/compiler/` |
| **Runtime** | Provides reactivity, DOM helpers, SSR, lifecycle | `packages/svelte/src/internal/` |

### 1.1 Compiler Pipeline (3-Phase)

The Svelte compiler transforms source text through three sequential phases. Each phase operates on the output of the previous one.

```
.svelte source text
       │
       ▼
┌──────────────────────────────────────┐
│  Phase 1: PARSE                      │
│  packages/svelte/src/compiler/       │
│  phases/1-parse/                     │
│  - Tokenize + parse HTML template    │
│  - Parse script blocks (acorn)       │
│  - Parse style blocks                │
│  - TypeScript support via            │
│    @sveltejs/acorn-typescript        │
│  Output: AST (Component/Module)      │
└──────────────────────────────────────┘
       │
       ▼
┌──────────────────────────────────────┐
│  Phase 2: ANALYZE                    │
│  packages/svelte/src/compiler/       │
│  phases/2-analyze/                   │
│  - Walk AST, resolve bindings        │
│  - Validate component structure      │
│  - Build scope tree                  │
│  - Check rune usage                  │
│  - CSS class/selector analysis       │
│  - Accessibility validation          │
│  Output: Annotated AST + Scope tree  │
└──────────────────────────────────────┘
       │
       ▼
┌──────────────────────────────────────┐
│  Phase 3: TRANSFORM                  │
│  packages/svelte/src/compiler/       │
│  phases/3-transform/                 │
│  - Generate JS (client or server)    │
│  - Generate CSS with scoping hashes  │
│  - Emit source maps                  │
│  Output: { js, css, warnings, ... }  │
└──────────────────────────────────────┘
```

> **NOTE**: The compiler is entirely stateless — it takes source text and options, and returns output. No global state, no file system access. All file I/O happens in the calling tool (Vite plugin, Rollup plugin, etc.).

#### Phase 1: Parse

The parser (`packages/svelte/src/compiler/phases/1-parse/`) produces a structured AST from `.svelte` source text. The parsing strategy is HTML-first: the template is parsed as HTML, with embedded script and expression blocks extracted during traversal.

Key files:

| File | Purpose |
|------|---------|
| `index.js` | Entry point, orchestrates HTML + script + style parsing |
| `read/expression.js` | Parses `{...}` template expressions using acorn |
| `read/script.js` | Extracts `<script>` blocks and hands off to acorn/TypeScript |
| `read/style.js` | Extracts `<style>` blocks |
| `utils/fuzzymatch.js` | `FuzzySet` class — fuzzy string matching for error message suggestions ("did you mean X?") |
| `utils/html.js` | HTML entity decoding, character utilities |
| `utils/bracket.js` | Matching brace/bracket tracking in template expressions |

TypeScript support is provided by `@sveltejs/acorn-typescript`, which extends acorn's grammar to handle TypeScript syntax inside `<script lang="ts">` blocks.

#### Phase 2: Analyze

The analysis phase (`packages/svelte/src/compiler/phases/2-analyze/`) walks the AST produced by the parser and enriches it with semantic information needed for code generation.

Responsibilities:
- **Scope resolution** — builds a nested scope tree resolving variable declarations, imports, and rune usages
- **Binding analysis** — determines which variables are reactive (`$state`, `$derived`) and how they flow through the component
- **Rune validation** — enforces correct usage of all runes (cannot call `$state()` at module level without `$state.raw()`, etc.)
- **CSS analysis** — identifies which CSS selectors are "used" by the template vs. unused (for dead-code elimination)
- **Accessibility validation** — checks against `aria-query` and `axobject-query` databases for ARIA attribute correctness
- **HTML tree validation** — enforces valid nesting (e.g., `<li>` inside `<ul>/<ol>`, no `<form>` inside `<form>`)

The `FuzzySet` class from `fuzzymatch.js` is used during analysis to suggest correct rune/attribute names when a typo is detected.

#### Phase 3: Transform

The transform phase (`packages/svelte/src/compiler/phases/3-transform/`) takes the analyzed AST and generates the final JavaScript and CSS output. There are two transform targets:

| Target | Entry Point | Output |
|--------|-------------|--------|
| **Client** | `3-transform/client/` | Browser JS — directly manipulates DOM using runtime helpers |
| **Server** | `3-transform/server/` | SSR JS — renders to HTML strings via server runtime |

CSS transformation applies a **DJB2 hash** of the component filename to generate a unique class suffix for each component's styles. This is the CSS scoping mechanism (see §1.5).

Source maps are generated using `magic-string` (for string manipulation with position tracking) and `@jridgewell/remapping` (for composing source maps across multiple transformation steps).

### 1.2 Runtime Architecture

The runtime is split into two environments that share interface contracts but have completely different implementations.

#### Client Runtime (`packages/svelte/src/internal/client/`)

The client runtime implements Svelte's **fine-grained reactivity** system based on a signal graph. Key modules:

| Module | Purpose |
|--------|---------|
| `runtime.js` | Core reactivity engine — signals, effects, reactions, dependency tracking |
| `render.js` | `mount()`, `hydrate()`, `unmount()` — component lifecycle at the DOM level |
| `context.js` | `setContext()` / `getContext()` implementation |
| `reactivity/sources.js` | `$state` sources — mutable reactive values |
| `reactivity/deriveds.js` | `$derived` — computed reactive values, lazy evaluation |
| `reactivity/effects.js` | `$effect` — side effects with automatic dependency tracking |
| `reactivity/equality.js` | Deep equality checks for derived invalidation |
| `dom/blocks/if.js` | `{#if}` block rendering |
| `dom/blocks/each.js` | `{#each}` block rendering with keying |
| `dom/blocks/snippet.js` | `{#snippet}` rendering |
| `dom/blocks/await.js` | `{#await}` block rendering |
| `dom/blocks/boundary.js` | Error/Svelte boundary blocks |
| `dom/elements/` | Element-level helpers (events, bindings, transitions, animations) |
| `errors.js` | Generated runtime error definitions |
| `warnings.js` | Generated runtime warning definitions |

**Signal graph model**: `$state` creates sources (writable nodes). `$derived` creates derived nodes (read-only, computed lazily). `$effect` creates effect nodes (run on change). When a source changes, all downstream deriveds are marked dirty and all downstream effects are scheduled for re-run. Dependency edges are tracked automatically during execution — any source read inside a derived or effect registers itself as a dependency.

**Batching**: Multiple state mutations can be batched to defer effect re-runs until the end of the batch, preventing cascading intermediate renders.

#### Server Runtime (`packages/svelte/src/internal/server/`)

The server runtime implements SSR. Key characteristics:

- Renders to HTML strings (or `ReadableStream` for streaming SSR)
- Most lifecycle hooks (`onMount`, `beforeUpdate`, `afterUpdate`) are **noops** on the server
- `onDestroy` **is the one lifecycle that runs on server** — used for cleanup in SSR contexts
- No reactivity graph — state is read-only during server rendering
- Hydration markers are injected into the output HTML for client takeover

### 1.3 Hydration System

Svelte uses **comment-based hydration markers** to identify dynamic DOM regions during client-side takeover of server-rendered HTML.

| Marker constant | Value | Meaning |
|-----------------|-------|---------|
| `HYDRATION_START` | `[` | Begin hydration block |
| `HYDRATION_START_ELSE` | `[!` | Begin else branch |
| `HYDRATION_START_FAILED` | `[?` | Begin failed state (boundary) |
| `HYDRATION_END` | `]` | End hydration block |

The client runtime (`render.js`) walks the DOM looking for these markers when `hydrate()` is called instead of `mount()`. On hydration:
1. Server-rendered HTML is preserved as-is where possible
2. Event listeners are attached
3. Reactive state is initialized
4. Dynamic regions bounded by markers are reconciled with the initial state

Hydration mismatches are caught and reported via the following ignorable (non-fatal) warnings:

```
hydration_attribute_changed   — attribute value differs between SSR and client
hydration_html_changed        — raw HTML content differs between SSR and client
```

> **NOTE**: These warnings indicate that SSR output diverges from what the client would render independently. They are safe to suppress in development but should be investigated in production as they represent inconsistent initial state.

### 1.4 CSS Scoping

Svelte generates scoped CSS by appending a unique class to every selector in a component's `<style>` block, and adding that class to every element in the component's template.

The scope hash is generated by the `hash()` function in `packages/svelte/src/utils.js`:

```javascript
// DJB2 hash → base-36 string
// Example: "Button.svelte" → "svelte-1x2y3z"
hash(str: string): string
```

The hash input is derived from the component's filename (configurable via `cssHash` compiler option). This means:
- Same file = same hash across builds (deterministic)
- Different files = different hashes (no collisions)
- Hash is a short base-36 string prepended with `svelte-`

CSS selectors are transformed at compile time:

```css
/* Input (in Button.svelte) */
button { color: red; }

/* Output */
button.svelte-abc123 { color: red; }
```

Template elements receive the class at compile time, not runtime — adding zero runtime overhead.

### 1.5 Event Delegation

Rather than attaching individual event listeners to each DOM element, Svelte delegates a fixed set of events to the document root. This reduces memory usage and listener overhead for large component trees.

**Delegated events** (attached once at document root):

```
beforeinput, click, change, dblclick, contextmenu,
focusin, focusout, input, keydown, keyup,
mousedown, mousemove, mouseout, mouseover, mouseup,
pointerdown, pointermove, pointerout, pointerover, pointerup,
touchend, touchmove, touchstart
```

**Passive events** (registered with `{ passive: true }`):

```
touchstart, touchmove
```

The `can_delegate_event(name)` utility in `packages/svelte/src/utils.js` checks whether an event name is in the delegated set. Events not in this list receive per-element listeners.

### 1.6 HTML Tree Validation

The compiler validates HTML nesting rules at compile time (`html-tree-validation.js` in the analyze phase).

**Autoclosing children** (elements that implicitly close when another is opened):

```
li, dt, dd, p, rt, rp, optgroup, option,
thead, tbody, tfoot, tr, td, th
```

**Disallowed nesting** (hard errors):
- `<form>` inside `<form>`
- `<a>` inside `<a>`
- `<button>` inside `<button>`
- Heading elements nested inside each other (`<h1>` inside `<h2>`, etc.)

> **NOTE**: Custom elements (tag names containing a `-`, e.g., `<my-button>`) bypass all HTML tree validation. This is intentional — custom element nesting rules are not standardized and vary by implementation.

### 1.7 Namespace Support

Svelte handles three XML namespaces:

| Constant | Value | Usage |
|----------|-------|-------|
| `NAMESPACE_HTML` | `http://www.w3.org/1999/xhtml` | Default namespace |
| `NAMESPACE_SVG` | `http://www.w3.org/2000/svg` | `<svg>` subtrees |
| `NAMESPACE_MATHML` | `http://www.w3.org/1998/Math/MathML` | `<math>` subtrees |

The compiler detects when it's inside an SVG or MathML context (using `is_svg(name)` / `is_mathml(name)` from `utils.js`) and adjusts element creation calls accordingly. SVG/MathML elements must be created with `document.createElementNS()` rather than `document.createElement()`.

Template flags control this behavior at runtime:

| Flag | Value | Meaning |
|------|-------|---------|
| `TEMPLATE_FRAGMENT` | `1` | Template is a document fragment |
| `TEMPLATE_USE_IMPORT_NODE` | `2` | Use `document.importNode()` |
| `TEMPLATE_USE_SVG` | `4` | Template is SVG namespace |
| `TEMPLATE_USE_MATHML` | `8` | Template is MathML namespace |

### 1.8 Version Disclosure

When Svelte mounts in a browser, it adds its version to a global set:

```javascript
// packages/svelte/src/internal/disclose-version.js
window.__svelte = window.__svelte || { v: new Set() };
window.__svelte.v.add(VERSION);
```

This allows browser devtools and diagnostics to detect which version(s) of Svelte are running on a page (multiple versions can coexist).

---

## 2. System Requirements

### 2.1 Runtime Requirements (for framework users)

| Requirement | Minimum | Notes |
|-------------|---------|-------|
| **Node.js** | 18.x | Required for build tooling; not present in browser bundles |
| **pnpm** | 9.0.0+ | Required for monorepo development; npm/yarn work for consuming the package |
| **Browsers** | Modern | ES2020+ output by default; exact targets depend on Vite/Rollup config |

### 2.2 Browser Support

Svelte's compiled output uses:
- `document.createElement` / `createTextNode` / `createComment`
- `element.cloneNode(true)` (for template cloning)
- `addEventListener` / `removeEventListener`
- ES2020 features (optional chaining, nullish coalescing, `Promise.allSettled`)
- `Proxy` (for fine-grained `$state` object reactivity)
- `WeakMap`, `WeakRef` (for memory-safe reactivity bookkeeping)

Minimum practical browser support: Chrome 80+, Firefox 78+, Safari 14+, Edge 80+.

For legacy browser support, downstream build tools must transpile and polyfill the compiled output.

### 2.3 Server-Side Rendering Requirements

SSR is pure JavaScript with no DOM dependency. The server runtime requires:
- A Node.js (or compatible) runtime
- No browser globals (`window`, `document`) — these are explicitly not referenced in the server runtime

### 2.4 Development Machine Requirements

For contributing to the Svelte monorepo:

```bash
node --version   # must be >= 18
pnpm --version   # must be >= 9.0.0
```

Optional but recommended:
- Playwright browsers for e2e tests: `pnpm exec playwright install`
- TypeScript language server for IDE support

---

## 3. Configuration Reference

### 3.1 `compile(source, options)` — Compiler API

The primary compiler entry point. Compiles a `.svelte` component to JavaScript and CSS.

```typescript
import { compile } from 'svelte/compiler';

const result = compile(source: string, options: CompileOptions): CompileResult;
```

**`CompileOptions`** (all fields optional unless noted):

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `filename` | `string` | `undefined` | Source filename. Used for CSS scoping hash and source map `sources`. Should be set in all real usage. |
| `name` | `string` | `'Component'` | Component class name in the generated JS. |
| `generate` | `'client' \| 'server' \| false` | `'client'` | Target environment. `false` returns AST only (no code generation). |
| `dev` | `boolean` | `false` | Enable development mode. Adds runtime checks, detailed error messages, `$inspect` support. |
| `accessors` | `boolean` | `false` | **(Legacy)** Generate getters/setters for props on component instances. Svelte 5 uses `$bindable` instead. |
| `immutable` | `boolean` | `false` | **(Legacy)** Assume props are immutable objects. |
| `hydratable` | `boolean` | `false` | Emit hydration markers for SSR takeover. Must match server-side `generate: 'server'` option. |
| `legacy` | `boolean \| object` | `false` | Enable Svelte 4 compatibility mode. Accepts `{ componentApi: 4 }` to use the Svelte 4 component API. |
| `customElement` | `boolean` | `false` | Compile as a custom element (Web Component). |
| `namespace` | `'html' \| 'svg' \| 'mathml'` | `'html'` | Root namespace of the component. Set to `'svg'` for SVG-only components. |
| `cssHash` | `(args: { hash, css, name, filename }) => string` | internal | Override CSS scope class generation. Default uses DJB2 hash of filename. |
| `preserveComments` | `boolean` | `false` | Include HTML comments in compiled output. |
| `preserveWhitespace` | `boolean` | `false` | Preserve insignificant whitespace between elements. |
| `runes` | `boolean \| undefined` | `undefined` | Force runes mode (`true`) or legacy mode (`false`). `undefined` = auto-detect from source. |
| `modernAst` | `boolean` | `false` | Return the modern (Svelte 5) AST format from `parse()`. |

**`CompileResult`**:

```typescript
{
  js: {
    code: string;
    map: SourceMap | null;
  };
  css: {
    code: string;
    map: SourceMap | null;
  } | null;
  warnings: Warning[];
  metadata: {
    runes: boolean;  // whether the component uses runes
  };
}
```

### 3.2 `compileModule(source, options)` — Module Compiler

Compiles `.svelte.js` / `.svelte.ts` module files (files that use Svelte runes but are not components — no template).

```typescript
import { compileModule } from 'svelte/compiler';

const result = compileModule(source: string, options: ModuleCompileOptions): CompileResult;
```

**`ModuleCompileOptions`**:

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `filename` | `string` | `undefined` | Source filename |
| `generate` | `'client' \| 'server'` | `'client'` | Target environment |
| `dev` | `boolean` | `false` | Development mode |

### 3.3 `parse(source, options)` — Parser API

Parses a `.svelte` source string to AST without code generation.

```typescript
import { parse } from 'svelte/compiler';

const ast = parse(source: string, options?: ParseOptions): AST.Root;
```

**`ParseOptions`**:

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `filename` | `string` | `undefined` | Source filename for error messages |
| `modern` | `boolean` | `false` | Return modern AST format (Svelte 5 node types) |

The returned `AST.Root` contains:
- `html` — fragment node with the component's template tree
- `instance` — `<script>` block AST (if present)
- `module` — `<script context="module">` / `<script module>` AST (if present)
- `css` — `<style>` block AST (if present)

### 3.4 `preprocess(source, preprocessors, options)` — Preprocessor API

Runs one or more preprocessors over a `.svelte` source string before compilation.

```typescript
import { preprocess } from 'svelte/compiler';

const result = await preprocess(
  source: string,
  preprocessors: PreprocessorGroup | PreprocessorGroup[],
  options?: { filename?: string }
): Promise<Processed>;
```

**`PreprocessorGroup`**: An object with optional `markup`, `script`, and `style` async functions. Each receives the relevant portion of the source and returns `{ code, map?, dependencies? }`.

**`Processed`**:
```typescript
{
  code: string;         // transformed source
  map: SourceMap | null;
  dependencies: string[];  // files to watch for changes
  toString(): string;
}
```

Common preprocessors consumed via this API:
- `svelte-preprocess` — TypeScript, SCSS, PostCSS, Pug support
- `@sveltejs/vite-plugin-svelte` — handles preprocessing transparently in Vite setups

### 3.5 `migrate(source, options)` — Migration API

Migrates Svelte 4 component syntax to Svelte 5 runes syntax.

```typescript
import { migrate } from 'svelte/compiler';

const result = migrate(source: string, options?: MigrateOptions): {
  code: string;
  // migration may not be complete for all patterns
};
```

> **IMPORTANT**: The migration tool handles the most common Svelte 4 patterns but may not cover all edge cases. Always review migrated output manually, especially for complex reactive statements (`$:`) and slot usage.

### 3.6 `svelte.config.js` — Project Configuration

The canonical project configuration file, consumed by SvelteKit and `@sveltejs/vite-plugin-svelte`.

```javascript
// svelte.config.js
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
  // Preprocessors run before the Svelte compiler
  preprocess: vitePreprocess(),

  // Svelte compiler options (passed to compile())
  compilerOptions: {
    // Options from §3.1, minus filename/name (set per-file by the plugin)
    runes: true,       // force runes mode project-wide
    dev: false,        // overridden by plugin based on Vite mode
  },

  // Vite plugin options (§3.7)
  vitePlugin: {
    inspector: true,
  },

  // SvelteKit-specific options (if using SvelteKit)
  kit: {
    adapter: adapter(),
  },
};

export default config;
```

### 3.7 Vite Plugin Options (`@sveltejs/vite-plugin-svelte`)

When using Svelte with Vite directly (without SvelteKit):

```javascript
// vite.config.js
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

export default defineConfig({
  plugins: [
    svelte({
      // All svelte.config.js options are accepted here too.
      // These take precedence if svelte.config.js also exists.

      include: /\.svelte$/,        // which files to process
      exclude: [],                  // which files to skip
      extensions: ['.svelte'],      // treated as Svelte files

      emitCss: true,               // extract CSS into separate chunks
      hot: true,                   // HMR (auto-disabled in SSR mode)

      preprocess: [],              // PreprocessorGroup[]
      compilerOptions: {},         // CompileOptions (§3.1)

      onwarn(warning, defaultHandler) {
        // filter or transform compiler warnings
        if (warning.code === 'a11y-click-events-have-key-events') return;
        defaultHandler(warning);
      },
    }),
  ],
});
```

### 3.8 Complete Runes Reference

Runes are special compiler directives — not real function calls, but syntax recognized by the Svelte compiler.

**State creation runes:**

| Rune | Description |
|------|-------------|
| `$state(initial)` | Reactive state. Objects/arrays are deeply reactive via `Proxy`. |
| `$state.raw(initial)` | Reactive state without deep proxy wrapping. Assignment triggers update; mutation does not. |
| `$state.snapshot(value)` | Takes a non-reactive deep copy of a `$state` value. |
| `$state.eager(initial)` | State that immediately runs effects (vs. default batched/deferred). |
| `$derived(expression)` | Computed value, re-evaluated when dependencies change. |
| `$derived.by(() => expression)` | Like `$derived` but accepts a function (for multi-statement deriveds). |

**Props runes:**

| Rune | Description |
|------|-------------|
| `$props()` | Declare component props. Destructure to access individual props. |
| `$props.id()` | Get the component's stable identity string (for `aria-labelledby`, etc.). |
| `$bindable(default?)` | Mark a prop as bindable (allows `bind:prop` from parent). |

**Effect runes:**

| Rune | Description |
|------|-------------|
| `$effect(() => { ... })` | Runs after DOM update when dependencies change. Cleanup via returned function. |
| `$effect.pre(() => { ... })` | Like `$effect` but runs before DOM update. |
| `$effect.tracking()` | Returns `true` if called inside a tracking context (effect/derived). |
| `$effect.root(() => { ... })` | Creates an isolated effect root not tied to component lifecycle. |
| `$effect.pending()` | Returns `true` if any `$state.eager` updates are pending. |

**Utility runes:**

| Rune | Description |
|------|-------------|
| `$inspect(value)` | Dev-mode only. Logs value and its dependencies to console. |
| `$inspect(value).with(fn)` | Custom inspector callback instead of `console.log`. |
| `$inspect.trace(label?)` | Traces which reactive sources triggered the current effect. |
| `$host()` | Inside custom elements only — returns the host DOM element. |

---

## 4. Deployment & Scaling

### 4.1 SSR Deployment

Svelte components compiled with `generate: 'server'` output a module with a `render()` function:

```javascript
// Compiled server output (simplified)
export function render(props, options) {
  const html = /* ... server-rendered HTML string ... */;
  const head = /* ... <head> content ... */;
  return { html, head };
}
```

**SvelteKit** handles this automatically via its adapter system. For manual SSR setups:

```javascript
import Component from './Component.svelte';

// Server handler (Express/Node example)
app.get('/', (req, res) => {
  const { html, head } = Component.render({ prop: 'value' });
  res.send(`
    <!DOCTYPE html>
    <html>
      <head>${head}</head>
      <body>${html}</body>
    </html>
  `);
});
```

```javascript
// Client hydration
import { hydrate } from 'svelte';
import Component from './Component.svelte';

hydrate(Component, {
  target: document.body,
  props: { prop: 'value' },
});
```

> **IMPORTANT**: The `hydratable: true` compiler option must be set for both the server and client builds. Without it, hydration markers are not emitted and `hydrate()` falls back to full client-side rendering.

### 4.2 Static Site Generation

For fully static output (no server runtime), prerender pages at build time. With SvelteKit:

```javascript
// src/routes/+page.js
export const prerender = true;
```

For standalone Svelte without SvelteKit, the pattern is:
1. Compile components with `generate: 'server'`
2. Run server rendering in a Node.js build script
3. Write HTML files to disk
4. Serve as static files

### 4.3 Custom Element Compilation

Svelte components can be compiled to native Web Components (custom elements):

```javascript
// compile option
compile(source, {
  customElement: true,
  name: 'my-button',  // must contain a hyphen
});
```

Or declare per-component in the `<svelte:options>` tag:

```svelte
<svelte:options customElement="my-button" />
```

Custom element behavior:
- Props become observed attributes (with type coercion)
- `<style>` is encapsulated in a Shadow DOM
- Lifecycle maps to `connectedCallback` / `disconnectedCallback`
- `$host()` rune provides access to the host element
- HTML tree validation is **disabled** for custom elements (see §1.6)

**Custom element options** (via `<svelte:options customElement={{ ... }}`):

```svelte
<svelte:options customElement={{
  tag: 'my-button',
  shadow: 'open',        // 'open' | 'none'
  props: {
    label: {
      reflect: true,     // sync prop changes back to attribute
      type: 'String',    // 'Boolean' | 'Number' | 'String' | 'Array' | 'Object'
      attribute: 'label' // attribute name (defaults to lowercased prop name)
    }
  },
  extend: (customElementClass) => class extends customElementClass {
    // custom lifecycle hooks
  }
}} />
```

### 4.4 Adapter Pattern (SvelteKit)

SvelteKit uses adapters to deploy to different hosting targets. An adapter is a package that:
1. Receives the SvelteKit build output
2. Transforms it for the target platform
3. Writes deployment files

Adapter interface (for custom adapter authors):

```javascript
/** @type {import('@sveltejs/kit').Adapter} */
export default function myAdapter(options = {}) {
  return {
    name: 'adapter-my-target',
    async adapt(builder) {
      // builder.generateManifest(), builder.copy(), builder.prerender(), etc.
    },
    supports: {
      read: () => true,  // whether adapter supports FS reads in load functions
    },
  };
}
```

### 4.5 Output Targets

Svelte's compiled output can target multiple module formats via the downstream bundler configuration. The Svelte compiler itself outputs ES module syntax; transformation to CJS/UMD/IIFE is handled by Rollup/Vite/webpack.

For libraries (not applications), the recommended distribution format is ESM with `exports` map in `package.json`, following Svelte's own package structure.

### 4.6 Multi-Version Coexistence

Multiple versions of Svelte can technically coexist on a single page (each adds its version to `window.__svelte.v`). However, this is not recommended for production:
- Each version carries its own runtime overhead
- Component trees from different versions cannot share context or stores
- Event delegation tables are per-version and may conflict

---

## 5. Operations

### 5.1 Monorepo Structure

```
svelte-monorepo/                    ← root package (name: "svelte-monorepo")
  packages/
    svelte/                         ← main package (published as "svelte")
      src/
        compiler/                   ← compiler source
          phases/
            1-parse/
            2-analyze/
            3-transform/
              client/
              server/
          utils/
        internal/                   ← runtime source
          client/
            dom/
              blocks/
              elements/
            reactivity/
          server/
          flags/                    ← experimental flag modules
        index.js                    ← public exports (non-compiler)
        index.d.ts                  ← TypeScript type definitions
      package.json
      rollup.config.js              ← build config for this package
  sites/
    svelte.dev/                     ← documentation site
    learn.svelte.dev/               ← interactive tutorial
  playgrounds/
    sandbox/                        ← Vite-based REPL/playground
  package.json                      ← root workspace config
  pnpm-workspace.yaml               ← pnpm workspace definition
```

### 5.2 Build System

The package is built with **Rollup** (not Vite). Vite is used only for the playground/sandbox.

**Root-level scripts** (`package.json` at monorepo root):

| Script | Command | Purpose |
|--------|---------|---------|
| `build` | `pnpm -r build` | Build all packages recursively |
| `check` | `svelte-check` | Type-check all `.svelte` files |
| `lint` | `eslint .` | Run ESLint |
| `format` | `prettier --write .` | Format all files |
| `test` | `vitest` | Run unit tests |
| `bench` | `vitest bench` | Run benchmarks |
| `bench:compare` | custom | Compare benchmark results |
| `bench:debug` | custom | Benchmark with debugging |
| `changeset:version` | `changeset version` | Bump version from changesets |
| `changeset:publish` | `changeset publish` | Publish to npm |

**Package-level scripts** (`packages/svelte/package.json`):

| Script | Purpose |
|--------|---------|
| `build` | `rollup -c` then `pnpm generate` |
| `dev` | `rollup -c -w` (watch mode) |
| `check` | TypeScript type checking |
| `generate` | Run all code generation scripts |
| `generate:version` | Write `src/version.js` from `package.json` |
| `generate:types` | `dts-buddy` — generate `.d.ts` from source |
| `prepublishOnly` | Full build + type generation before publish |
| `knip` | `knip` — detect dead exports/imports |

**Build process in detail:**

```bash
# Full build of packages/svelte
cd packages/svelte
pnpm build
# 1. rollup -c           → bundles src/ → dist/
# 2. pnpm generate       → code-gen (version.js, error messages, types)
# 3. dts-buddy           → generates TypeScript declarations
```

The Rollup configuration (`packages/svelte/rollup.config.js`) produces multiple output bundles corresponding to the package exports map (see §3.8 below).

### 5.3 Code Generation

Several source files in `packages/svelte/src/` are **generated** and should not be hand-edited:

| Generated file | Generator | Content |
|----------------|-----------|---------|
| `src/version.js` | `generate:version` | `export const VERSION = '5.55.4'` |
| `src/internal/client/errors.js` | `generate:errors` | Runtime error message functions |
| `src/internal/client/warnings.js` | `generate:warnings` | Runtime warning functions |
| `src/compiler/errors.js` | `generate:errors` | Compiler error message functions |
| `src/compiler/warnings.js` | `generate:warnings` | Compiler warning functions |

Error and warning functions follow a pattern:

```javascript
// Generated — do not edit
export function invalid_rune_usage(node, rune) {
  // throws CompileDiagnostic with URL link
  e(node, "invalid_rune_usage", `The \`${rune}\` rune can only be used inside a .svelte or .svelte.js file\nhttps://svelte.dev/e/invalid_rune_usage`);
}
```

### 5.4 Testing Strategy

Tests live in `packages/svelte/tests/` and are organized by category:

| Category | Directory | Runner | Purpose |
|----------|-----------|--------|---------|
| **Runtime** | `tests/runtime/` | Vitest | Component behavior in jsdom |
| **CSS** | `tests/css/` | Vitest | CSS scoping, selector transforms |
| **Parser** | `tests/parser/` | Vitest | AST output for given inputs |
| **Validator** | `tests/validator/` | Vitest | Compiler error/warning triggering |
| **Hydration** | `tests/hydration/` | Vitest | SSR → client hydration correctness |
| **Server** | `tests/server/` | Vitest | SSR output correctness |
| **Motion** | `tests/motion/` | Vitest | `svelte/motion` tweens/springs |
| **Transition** | `tests/transition/` | Vitest | `svelte/transition` functions |
| **e2e** | `tests/e2e/` | Playwright | Full browser interaction tests |

Run tests:

```bash
# All tests
pnpm test

# Specific category (Vitest filter)
pnpm test -- --reporter=verbose runtime

# e2e (requires Playwright browsers)
pnpm exec playwright install
pnpm test:e2e
```

Each test category follows a **fixture pattern**: a directory of input files (`input.svelte`, `input.js`) and expected output files (`output.js`, `expected.css`). The test runner compiles the input and diffs against the expected output.

To update expected outputs after intentional changes:

```bash
pnpm test -- --update-snapshots
```

### 5.5 Changesets Workflow

Version management uses `changesets` (from `@changesets/cli`).

**Adding a changeset** (required for any user-visible change):

```bash
pnpm changeset
# Interactive prompt:
# 1. Select packages changed (svelte)
# 2. Select semver bump (major/minor/patch)
# 3. Write summary of change
# Creates .changeset/random-name.md
```

**Release process:**

```bash
# 1. Accumulate changesets from PRs
# 2. Version bump (updates CHANGELOG.md, package.json)
pnpm changeset:version

# 3. Review CHANGELOG, commit
git commit -am "chore: version packages"

# 4. Publish to npm
pnpm changeset:publish
# Internally runs: pnpm prepublishOnly && npm publish
```

### 5.6 Linting Configuration

ESLint is configured with a custom rule:

**`no_compiler_imports`** — Prevents any file under `packages/svelte/src/` (excluding `compiler/`) from importing anything from `packages/svelte/src/compiler/`. This enforces the hard separation between compiler and runtime — the runtime must not depend on the compiler.

Location: `eslint-plugin/` or inline in `eslint.config.js`.

Prettier handles formatting. Configuration is in `.prettierrc` at the repository root:
- Tab width: configurable (check `.prettierrc`)
- Single quotes vs double: per config
- No semicolons: per config

### 5.7 Benchmarking

Svelte maintains a benchmark suite for tracking reactivity and rendering performance:

```bash
# Run benchmarks
pnpm bench

# Compare two commits
pnpm bench:compare

# Debug benchmark with verbose output
pnpm bench:debug
```

Benchmarks use Vitest's `bench` API and measure:
- Reactivity update propagation throughput
- DOM rendering time for large `{#each}` blocks
- Keyed vs. non-keyed reconciliation

### 5.8 Continuous Integration

The repository uses GitHub Actions. Key CI checks:

| Check | Trigger | Purpose |
|-------|---------|---------|
| Type check | PR, push | `tsc` over all packages |
| Lint | PR, push | ESLint + Prettier check |
| Unit tests | PR, push | Full Vitest suite |
| e2e tests | PR, push | Playwright browser tests |
| Benchmark | Scheduled | Regression detection |

---

## 6. Performance

### 6.1 Event Delegation Model

Delegating events to the document root instead of per-element provides significant memory savings for large component trees. A list of 10,000 items with click handlers uses 1 document listener instead of 10,000.

The delegation layer dispatches to the correct handler via a lookup table keyed by the target element, walking up the DOM tree until a handler is found (event bubbling is preserved semantically).

**Implications for integrators:**
- `event.stopPropagation()` works as expected within Svelte trees
- Events from non-Svelte DOM (e.g., vanilla JS children) are not captured by the delegation table
- The delegation table is set up once when any component using a given event type is first mounted

### 6.2 CSS Scoping Strategy

Zero-runtime-cost CSS scoping: the scope class (e.g., `.svelte-abc123`) is added to DOM elements by the **compiled code** at element creation time, not by runtime class manipulation. There is no `className` mutation after initial render.

CSS specificity is unchanged — scope class adds one class-level specificity point, same for all selectors in the file.

**CSS dead code elimination**: The compiler tracks which selectors are referenced in the template. Unused selectors are removed from the output CSS entirely (with a dev-mode warning). This is done in the analyze phase.

### 6.3 Reactivity Optimization

**Fine-grained updates**: Only the exact DOM nodes that depend on a changed signal are updated. There is no virtual DOM diffing — the signal graph encodes exactly which DOM operation corresponds to which reactive value.

**Lazy derivation**: `$derived` values are not computed until read. If a derived is never read in a given render cycle, it is never computed.

**Batching**: Multiple `$state` mutations in a single synchronous block are batched — effects run once after all mutations, not once per mutation.

**Keyed `{#each}` blocks**: Using a key expression (`{#each items as item (item.id)}`) enables efficient list reconciliation. Unkeyed each blocks rebuild their DOM on reorder. A known performance regression was identified in issue #18120: keyed `{#each}` is currently slower than non-keyed in certain scenarios — track for fix.

### 6.4 Hydration Performance

Svelte's hydration avoids full re-rendering:
- Static HTML from SSR is preserved as-is
- Only dynamic regions (bounded by hydration markers) are visited
- Event listeners are attached in a single pass over the hydration markers
- `$state` is initialized from the rendered values where possible

### 6.5 Tree-Shaking

Each export in the Svelte package is side-effect-free (marked in `package.json` with `"sideEffects": false` or equivalent). Bundlers can eliminate unused exports:

- A project that uses no transitions imports nothing from `svelte/transition`
- SSR builds tree-shake away client-only DOM manipulation code
- The `esm-env` package provides `BROWSER`/`SERVER` constants that enable static dead-code elimination by bundlers

### 6.6 Template Cloning

For elements rendered in `{#each}` loops, Svelte uses `document.importNode()` (when `TEMPLATE_USE_IMPORT_NODE` flag is set) to clone a pre-built template fragment instead of creating elements one by one with `createElement`. This is faster for complex subtrees.

---

## 7. Security

### 7.1 HTML Escaping

User-provided strings rendered inside `{expression}` template interpolations are **HTML-escaped by default**. The escape function is `escape_html()` in the runtime.

Characters escaped: `&`, `<`, `>`, `"`, `'`

```svelte
<!-- Safe: user input is escaped -->
<p>{userInput}</p>

<!-- UNSAFE: raw HTML injection — only use with trusted content -->
<p>{@html trustedHtmlString}</p>
```

> **WARNING**: `{@html ...}` bypasses HTML escaping entirely and injects raw HTML into the DOM. Never use `{@html}` with unsanitized user input. If user content must be rendered as HTML, sanitize it with a library like `DOMPurify` before passing to `{@html}`.

### 7.2 Trusted Types Support

Svelte includes support for the [Trusted Types API](https://w3c.github.io/webappsec-trusted-types/dist/spec/), a browser security feature that prevents DOM XSS by enforcing that only "trusted" values can be assigned to dangerous sinks like `innerHTML`.

The `@types/trusted-types` dev dependency provides TypeScript types for the Trusted Types API. Svelte's runtime respects Trusted Types policies when setting `innerHTML` for `{@html}` blocks — it will call the active policy's `createHTML()` method if a policy is enforced.

To use Svelte with a Trusted Types CSP:
```
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types svelte-policy;
```

### 7.3 CSS Injection Prevention

The CSS scoping mechanism (§1.4) means component styles cannot leak out and affect other components' elements. This prevents:
- Third-party component styles from overriding application styles unexpectedly
- User-provided class names from triggering unintended style application

However, CSS scoping is **not a security boundary** — it's a specificity mechanism. Dynamic style bindings (`style:property={value}`) that include user input should be validated:

```svelte
<!-- Potentially dangerous if `userColor` is not validated -->
<div style:color={userColor}>...</div>
```

CSS custom properties set via `--property={value}` bindings are safe — they cannot inject new CSS rules, only set values.

### 7.4 XSS Prevention in Templates

Svelte's compile-time template processing provides strong XSS protection:

| Template syntax | Safety |
|-----------------|--------|
| `{expression}` | Safe — HTML-escaped |
| `{@html expression}` | **Unsafe** — raw injection, use with caution |
| `on:click={handler}` | Safe — compiles to `addEventListener`, not inline script |
| `href={value}` | Safe for `https://` URLs; `javascript:` is blocked in dev mode |
| `style:prop={value}` | Safe — CSS property values, not rule injection |

> **CAUTION**: Svelte does not sanitize `href` attribute values in production builds beyond emitting a dev-mode warning for `javascript:` URLs. Validate user-provided URLs server-side before binding to `href`.

### 7.5 `svelte/internal` Import Guard

`packages/svelte/src/internal/index.js` deliberately throws a runtime error when imported:

```javascript
// svelte/internal — DO NOT IMPORT
// This module existed in Svelte 4 but is private in Svelte 5.
// The internal API changed incompatibly between versions.
// Import from svelte, svelte/store, svelte/motion, etc. instead.
throw new Error('...');
```

This is enforced at runtime (not just as a TypeScript type error) to prevent libraries and user code from depending on private internals that may change without notice.

The ESLint rule `no_compiler_imports` enforces the equivalent boundary at development time within the monorepo itself.

### 7.6 Content Security Policy

Svelte's compiled output does not use `eval()` or `Function()` constructor by default — all reactivity and DOM manipulation is compiled to static code. This makes Svelte compatible with strict CSP `script-src` without `unsafe-eval`.

Exception: Some legacy compatibility features in Svelte 4 mode may require `unsafe-eval`. Svelte 5 runes mode is `unsafe-eval`-free.

---

## 8. Developer Internals

### 8.1 Complete Repository Structure

```
packages/svelte/
  src/
    compiler/
      phases/
        1-parse/
          index.js                ← parser entry point
          read/
            expression.js         ← template expression parser
            script.js             ← <script> block parser
            style.js              ← <style> block parser
          utils/
            fuzzymatch.js         ← FuzzySet for error suggestions
            html.js               ← HTML entity utils
            bracket.js            ← bracket matching
        2-analyze/
          index.js                ← analysis entry point
          css/                    ← CSS analysis
          a11y.js                 ← accessibility validation
          html-tree-validation.js ← nesting validation
        3-transform/
          client/                 ← client-side code generation
          server/                 ← server-side code generation
          css/                    ← CSS transform + scoping
      utils/
        compile_diagnostic.js     ← CompileDiagnostic class
        mapped_code.js            ← MappedCode class
      errors.js                   ← GENERATED compiler errors
      warnings.js                 ← GENERATED compiler warnings
      index.js                    ← svelte/compiler exports
    internal/
      client/
        dom/
          blocks/
            if.js                 ← {#if} rendering
            each.js               ← {#each} rendering
            snippet.js            ← {#snippet} rendering
            await.js              ← {#await} rendering
            boundary.js           ← error boundary rendering
            key.js                ← {#key} block
            html.js               ← {@html} rendering
            svelte-element.js     ← <svelte:element>
            svelte-component.js   ← <svelte:component>
          elements/
            events.js             ← event handling + delegation
            bindings/             ← bind: directives
            transitions.js        ← transition: directives
            animations.js         ← animate: directives
            attachments.js        ← {@attach} directive
        reactivity/
          sources.js              ← $state implementation
          deriveds.js             ← $derived implementation
          effects.js              ← $effect implementation
          equality.js             ← deep equality
        runtime.js                ← signal graph core
        render.js                 ← mount/hydrate/unmount
        context.js                ← setContext/getContext
        errors.js                 ← GENERATED runtime errors
        warnings.js               ← GENERATED runtime warnings
      server/
        index.js                  ← SSR rendering
        context.js                ← server context
      flags/
        async.js                  ← experimental async flag
        legacy.js                 ← legacy mode flag
        tracing.js                ← effect tracing flag
      disclose-version.js         ← window.__svelte.v registration
      index.js                    ← throws error (private guard)
    constants.js                  ← all bitflag constants
    utils.js                      ← shared utility functions
    index.js                      ← public API (non-compiler)
    index.d.ts                    ← TypeScript declarations
    store/                        ← svelte/store package
    motion/                       ← svelte/motion package
    transition/                   ← svelte/transition package
    animate/                      ← svelte/animate package
    easing/                       ← svelte/easing package
    events/                       ← svelte/events package
    attachments/                  ← svelte/attachments package
    reactivity/                   ← svelte/reactivity package
    legacy/                       ← svelte/legacy package
  dist/                           ← built output (gitignored)
  package.json
  rollup.config.js
```

### 8.2 Package Exports Map

The `packages/svelte/package.json` exports map defines all public entry points:

| Export | Condition | Purpose |
|--------|-----------|---------|
| `.` | `browser` → client, default → server | Main runtime (auto-selects client/server) |
| `./compiler` | — | Compiler API (`compile`, `parse`, etc.) |
| `./store` | — | Svelte store primitives (`writable`, `readable`, `derived`) |
| `./motion` | — | `tweened`, `spring` motion stores |
| `./transition` | — | Built-in transitions (`fade`, `fly`, `slide`, etc.) |
| `./animate` | — | Built-in animations (`flip`) |
| `./easing` | — | Easing functions |
| `./events` | — | `on()` utility for event handling |
| `./attachments` | — | `{@attach}` directive utilities |
| `./reactivity` | — | Standalone reactive primitives |
| `./reactivity/window` | — | Window-level reactive values |
| `./server` | — | Explicit server runtime import |
| `./legacy` | — | Svelte 4 compatibility API |
| `./internal` | — | **Throws error** — private, do not use |
| `./internal/client` | — | Internal client runtime (semi-public for tooling) |
| `./internal/server` | — | Internal server runtime (semi-public for tooling) |
| `./internal/flags/*` | — | Feature flag modules |

### 8.3 Bitflag Constants

Svelte uses integer bitflags extensively for compact state representation. Understanding these is essential for reading the compiler and runtime source.

**`{#each}` block flags** (`EACH_*`):

| Constant | Value | Meaning |
|----------|-------|---------|
| `EACH_ITEM_REACTIVE` | `1` | Items are reactive signals |
| `EACH_INDEX_REACTIVE` | `2` | Index is reactive |
| `EACH_IS_CONTROLLED` | `4` | Each block is "controlled" (no wrapping element) |
| `EACH_IS_ANIMATED` | `8` | Each uses `animate:` directive |
| `EACH_ITEM_IMMUTABLE` | `16` | Items treated as immutable |

**Props flags** (`PROPS_*`):

| Constant | Value | Meaning |
|----------|-------|---------|
| `PROPS_IS_IMMUTABLE` | `1` | Props object is immutable |
| `PROPS_IS_RUNES` | `2` | Parent is in runes mode |
| `PROPS_IS_UPDATED` | `4` | Props have been updated at least once |
| `PROPS_IS_BINDABLE` | `8` | Prop is bindable (`$bindable`) |
| `PROPS_IS_LAZY_INITIAL` | `16` | Initial value is lazily evaluated |

**Transition flags** (`TRANSITION_*`):

| Constant | Value | Meaning |
|----------|-------|---------|
| `TRANSITION_IN` | `1` | Transition plays on enter |
| `TRANSITION_OUT` | `2` | Transition plays on exit |
| `TRANSITION_GLOBAL` | `4` | Global transition (not scoped to block) |

Usage pattern in source:

```javascript
// Setting flags
const flags = EACH_ITEM_REACTIVE | EACH_INDEX_REACTIVE;  // = 3

// Checking flags
if (flags & EACH_IS_ANIMATED) { ... }

// Clearing a flag
flags &= ~EACH_ITEM_REACTIVE;
```

### 8.4 Signal Graph Implementation

The core reactivity engine in `runtime.js` implements a **push-pull signal graph**:

**Node types:**
- **Source** (writable signal) — created by `$state`. Has a `value` and a set of subscribers.
- **Derived** (computed signal) — created by `$derived`. Has a computation function, cached value, and dirty flag.
- **Effect** — created by `$effect`. Has a side-effect function and cleanup return value.

**Dependency tracking:**
- A global "current consumer" pointer is set when running a derived or effect
- Any source read during execution registers the current consumer as a subscriber
- Reads outside a tracking context (no current consumer) do not register subscriptions

**Update cycle:**
1. Source value changes → mark all subscribers dirty
2. Schedule microtask to flush effects
3. In flush: run dirty effects in topological order
4. Effects re-run their function, re-registering dependencies (stale dependencies are pruned)
5. Cleanup functions from previous run are called before re-run

**Effect scheduling:**
- Effects are scheduled via `Promise.resolve().then()` (microtask queue)
- `$effect.pre` runs before DOM updates (synchronous flush)
- `$effect` runs after DOM updates (async flush)

### 8.5 Compiler AST Node Types

The Svelte AST (returned by `parse()`) uses these primary node types:

**Fragment nodes:**
- `Root` — top-level component AST
- `Fragment` — ordered list of child nodes

**Template nodes:**
- `Element` — HTML elements (`<div>`, `<span>`, etc.)
- `Component` — Svelte components (`<MyComponent>`)
- `SvelteComponent` — `<svelte:component>`
- `SvelteElement` — `<svelte:element>`
- `SvelteSelf` — `<svelte:self>` (recursive component)
- `SvelteFragment` — `<svelte:fragment>`
- `SvelteHead` — `<svelte:head>`
- `SvelteBody` — `<svelte:body>`
- `SvelteWindow` — `<svelte:window>`
- `SvelteDocument` — `<svelte:document>`
- `SvelteOptions` — `<svelte:options>`
- `Text` — static text node
- `ExpressionTag` — `{expression}` interpolation
- `HtmlTag` — `{@html expression}` raw HTML
- `ConstTag` — `{@const x = ...}` local constant
- `DebugTag` — `{@debug variable}` debug helper
- `RenderTag` — `{@render snippet()}` snippet invocation
- `AttachTag` — `{@attach action}` attachment

**Block nodes:**
- `IfBlock` — `{#if}...{:else if}...{:else}...{/if}`
- `EachBlock` — `{#each}...{:else}...{/each}`
- `AwaitBlock` — `{#await}...{:then}...{:catch}...{/await}`
- `KeyBlock` — `{#key}...{/key}`
- `SnippetBlock` — `{#snippet name()}...{/snippet}`

**Attribute nodes:**
- `Attribute` — regular HTML attribute
- `SpreadAttribute` — `{...spread}` props spread
- `BindDirective` — `bind:value`
- `ClassDirective` — `class:active={...}`
- `StyleDirective` — `style:color={...}`
- `EventHandler` — `on:click={handler}` (legacy) or `onclick={handler}`
- `TransitionDirective` — `transition:fade`
- `AnimateDirective` — `animate:flip`
- `UseDirective` — `use:action`
- `LetDirective` — `let:slot` (legacy slots)
- `AttachDirective` — `{@attach}`

### 8.6 Key Utility Classes

**`CompileDiagnostic`** (`packages/svelte/src/compiler/utils/compile_diagnostic.js:51`):

The base class for all compiler errors and warnings. Extends `Error` with:
- `code` — machine-readable error code (e.g., `invalid_rune_usage`)
- `start` / `end` — source position (`{ line, column, character }`)
- `filename` — source file path
- URL to `svelte.dev/e/{code}` or `svelte.dev/w/{code}` for documentation

`InternalCompileError` extends `CompileDiagnostic` for compiler bugs (not user errors).

**`MappedCode`** (`packages/svelte/src/compiler/utils/mapped_code.js:75`):

Represents a code string with an associated source map. Used during code generation to accumulate transformed code while maintaining position mapping back to source. Built on `magic-string`.

**`FuzzySet`** (`packages/svelte/src/compiler/phases/1-parse/utils/fuzzymatch.js:124`):

A fuzzy string matching data structure used for "did you mean X?" suggestions in error messages. When the user writes `$stat` instead of `$state`, `FuzzySet` finds the closest matching rune name.

### 8.7 Error System Architecture

Compiler errors follow a structured pattern:

```javascript
// In errors.js (generated)
export function invalid_rune_usage(node, rune) {
  e(node, "invalid_rune_usage", `...message...\nhttps://svelte.dev/e/invalid_rune_usage`);
}

// Usage in analyzer
import * as e from '../errors.js';
e.invalid_rune_usage(node, '$state');
```

Error codes are organized by category:

| Prefix | Category |
|--------|----------|
| `options_*` | Compiler option validation |
| `rune_*` | Rune usage errors |
| `props_*` | Props-related errors |
| `state_*` | State-related errors |
| `bind_*` | Binding errors |
| `css_*` | CSS errors |
| `block_*` | Block syntax errors |
| `animation_*` | Animation directive errors |
| `attribute_*` | Attribute errors |
| `snippet_*` | Snippet errors |
| `legacy_*` | Legacy Svelte 4 feature errors in Svelte 5 mode |
| `typescript_*` | TypeScript-specific errors |

### 8.8 Experimental Flags

Experimental features are controlled via flag modules in `packages/svelte/src/internal/flags/`:

| Flag module | Feature | Status |
|-------------|---------|--------|
| `async.js` | Async component support (`{#await}` improvements, async snippets) | Experimental |
| `legacy.js` | Legacy Svelte 4 compatibility behaviors | Stable (used by `legacy` option) |
| `tracing.js` | Effect dependency tracing (`$inspect.trace`) | Dev-mode feature |

These flags can be toggled at the application entry point before any Svelte components are imported:

```javascript
// Enable experimental async support
import { set_async_mode_flag } from 'svelte/internal/flags/async';
set_async_mode_flag(true);
```

> **IMPORTANT**: Experimental flags are subject to breaking changes without semver consideration. Do not use in production without accepting this risk.

### 8.9 Ignorable Runtime Warnings

The following runtime warnings are commonly suppressed in production or specific development scenarios. They indicate non-critical conditions:

| Warning code | Description | When to suppress |
|--------------|-------------|------------------|
| `await_waterfall` | Nested `{#await}` blocks create a waterfall of requests | When waterfall is intentional |
| `await_reactivity_loss` | Promise inside `{#await}` is not reactive | When using non-reactive promises intentionally |
| `state_snapshot_uncloneable` | `$state.snapshot()` found an uncloneable value | When snapshots include complex objects |
| `binding_property_non_reactive` | Binding targets a property that isn't reactive | When binding to computed/external properties |
| `hydration_attribute_changed` | Attribute differs between SSR and client | When difference is intentional (e.g., random IDs) |
| `hydration_html_changed` | Raw HTML differs between SSR and client | When SSR and client content legitimately differ |
| `ownership_invalid_binding` | A component binds to a prop it doesn't own | When intentional cross-component binding is needed |
| `ownership_invalid_mutation` | A component mutates state it doesn't own | When intentional shared state mutation is needed |

Suppress specific warnings in `svelte.config.js` or via the `onwarn` plugin option:

```javascript
// svelte.config.js
export default {
  compilerOptions: {
    // warnings are suppressed per-component via svelte-ignore comment
  },
};
```

```svelte
<!-- Suppress in a specific file -->
<!-- svelte-ignore ownership_invalid_mutation -->
{parent.value = 'changed'}
```

### 8.10 Contributing Guide

**Repository setup:**

```bash
git clone https://github.com/sveltejs/svelte
cd svelte
pnpm install        # install all workspace dependencies
pnpm build          # initial build (required before tests)
```

**Development workflow:**

```bash
cd packages/svelte
pnpm dev            # Rollup watch mode — rebuilds on source changes

# In another terminal
pnpm test           # Run tests (watches on source changes with Vitest)
```

**Making a change:**

1. Edit source in `packages/svelte/src/`
2. Build: `pnpm build` (or watch mode handles it)
3. Add/update tests in `packages/svelte/tests/`
4. Update snapshots if needed: `pnpm test -- --update-snapshots`
5. Add a changeset: `pnpm changeset` (required for all user-visible changes)
6. Run linting: `pnpm lint && pnpm check`

**Test fixture pattern:**

Most test categories use input/output fixture directories:

```
tests/runtime/samples/my-test-case/
  main.svelte    ← input component
  _config.js     ← test configuration (expected behavior)
```

```
tests/css/samples/basic/
  input.svelte   ← input component
  output.css     ← expected CSS output
```

**Compiler error tests:**

```
tests/validator/samples/rune-invalid-location/
  input.svelte   ← input that should produce an error
  errors.json    ← expected error codes and messages
```

---

## 9. Integration Points

### 9.1 Vite Plugin Integration

`@sveltejs/vite-plugin-svelte` is the primary integration layer between Svelte and Vite-based toolchains.

**Plugin lifecycle:**

1. **`transform` hook** — intercepts `.svelte` and `.svelte.js` files
   - Runs preprocessors (if configured)
   - Calls `compile()` or `compileModule()` with the preprocessed source
   - Returns `{ code, map }` for Vite's module graph
2. **`handleHotUpdate` hook** — manages HMR
   - Re-compiles changed `.svelte` files
   - Injects HMR update payload using Svelte's HMR API
   - Invalidates dependent modules in Vite's module graph
3. **CSS extraction** — the plugin separates CSS from the JS output and registers it as a virtual module (`?svelte&type=style`)

**Plugin configuration** is detailed in §3.7.

### 9.2 Rollup Plugin Integration

For non-Vite Rollup builds, use `rollup-plugin-svelte`:

```javascript
// rollup.config.js
import svelte from 'rollup-plugin-svelte';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import css from 'rollup-plugin-css-only';

export default {
  input: 'src/main.js',
  output: { file: 'public/bundle.js', format: 'iife' },
  plugins: [
    svelte({
      compilerOptions: { dev: !production },
      preprocess: sveltePreprocess(),
    }),
    css({ output: 'bundle.css' }),
    nodeResolve({ browser: true, exportConditions: ['browser'] }),
  ],
};
```

> **IMPORTANT**: When resolving Svelte's package, ensure the `browser` export condition is set. Without it, the server runtime is loaded in browser bundles. In Rollup: `exportConditions: ['browser']`. In Webpack: set `resolve.conditionNames`.

### 9.3 Preprocessors

Preprocessors transform `.svelte` source before the Svelte compiler sees it. They enable TypeScript, SCSS, PostCSS, and other language transformations.

**Preprocessor API contract:**

```typescript
interface PreprocessorGroup {
  name?: string;

  markup?: (options: {
    content: string;
    filename?: string;
  }) => Processed | Promise<Processed>;

  script?: (options: {
    content: string;
    markup: string;
    attributes: Record<string, string | boolean>;
    filename?: string;
  }) => Processed | Promise<Processed>;

  style?: (options: {
    content: string;
    markup: string;
    attributes: Record<string, string | boolean>;
    filename?: string;
  }) => Processed | Promise<Processed>;
}

interface Processed {
  code: string;
  map?: string | object;  // source map
  dependencies?: string[];  // files to watch
  attributes?: Record<string, string | boolean>;  // updated attributes
}
```

**Multiple preprocessors** are applied in sequence. Each receives the output of the previous:

```javascript
preprocess([
  vitePreprocess(),          // TypeScript, SCSS
  myCustomPreprocessor(),    // custom transformation
])
```

### 9.4 Store Interoperability

`svelte/store` provides the store contract used by many Svelte libraries. Any object implementing this contract is "store-compatible":

```typescript
interface Readable<T> {
  subscribe(run: (value: T) => void, invalidate?: () => void): () => void;
}

interface Writable<T> extends Readable<T> {
  set(value: T): void;
  update(updater: (value: T) => T): void;
}
```

**Stores and runes interop**: In Svelte 5 runes mode, stores are auto-subscribed with `$store` prefix syntax (Svelte 4 behavior). Alternatively, use `$state` with manual subscription:

```javascript
// Adapting an external store to $state
import { myStore } from './external.js';
import { onDestroy } from 'svelte';

let value = $state(undefined);
const unsubscribe = myStore.subscribe(v => { value = v; });
onDestroy(unsubscribe);
```

### 9.5 `svelte/reactivity` — Standalone Reactivity

The `svelte/reactivity` package exports reactive primitives for use outside of Svelte components:

```javascript
import { SvelteMap, SvelteSet, SvelteURL, SvelteDate } from 'svelte/reactivity';
import { MediaQuery } from 'svelte/reactivity/window';

// Reactive Map — mutations trigger updates
const map = new SvelteMap();
map.set('key', 'value');

// Reactive window media query
const isSmall = new MediaQuery('(max-width: 600px)');
```

These are subclasses of their standard counterparts with Svelte's reactivity wired in.

### 9.6 `svelte/attachments` — DOM Attachments

The `{@attach}` directive and `svelte/attachments` package provide a composable alternative to `use:` actions:

```javascript
import { on, createAttachmentKey } from 'svelte/attachments';

// Create a reusable attachment
const tooltip = createAttachmentKey();

// Use in template
// <div {@attach tooltip}>...</div>
```

Attachments are functions that receive the DOM element and return an optional cleanup function. They compose naturally with the `@attach` attachment syntax.

### 9.7 TypeScript Integration

Svelte provides full TypeScript support:

**Component typing:**

```typescript
// MyComponent.svelte — TypeScript in <script lang="ts">
<script lang="ts">
  interface Props {
    name: string;
    count?: number;
  }
  
  const { name, count = 0 }: Props = $props();
</script>
```

**Generic components:**

```svelte
<script lang="ts" generics="T extends { id: string }">
  const { items }: { items: T[] } = $props();
</script>
```

**`SvelteComponent` base type** (for dynamic `<svelte:component>`):

```typescript
import type { SvelteComponent, ComponentType } from 'svelte';

let component: ComponentType<SvelteComponent<{ name: string }>> = MyComponent;
```

`SvelteComponentTyped<Props, Events, Slots>` is the Svelte 4 typed base class, preserved for compatibility in `svelte/legacy`. In Svelte 5, components are typed via their props interface directly.

**Type generation**: `dts-buddy` generates `.d.ts` files from the Svelte package source during the build (`pnpm generate:types`). This produces accurate types for all exported APIs including the compiler.

---

## Known Issues & Active Bugs

Based on open GitHub issues at source commit `fcaa8ce`:

| Issue | Title | Affected area | Status |
|-------|-------|---------------|--------|
| #17027 | `lifecycle_outside_component` in SSR builds | SSR / lifecycle | Open |
| #18095 | `$effect.pending()` broken with `$state.eager` | Reactivity | Open |
| #18096 | Detached DOM subtrees retained after destroy | Memory / DOM | Open |
| #18120 | Keyed each worse performance than non-keyed | Performance | Open |
| #8089 | a11y mouse events warning with focusin/focusout | A11y warnings | Open |
| #17327 | `video` `muted` attribute not rendering in SSR | SSR attributes | Open |
| #18119 | `@const` referencing `let` slot prop regression | Compiler | Open |
| #18097 | Spurious `derived_inert` warnings | Reactivity warnings | Open |
| #18103 | Memory leak with `$effect` + parent prop | Memory | Open |
| #18094 | DOM leak on unresolved promises | Memory / DOM | Open |
| #18092 | Style hashing with filename causes leaks | CSS / Memory | Open |

> **NOTE**: These issues were open at the time of document generation. Check the [Svelte GitHub repository](https://github.com/sveltejs/svelte/issues) for current status.

---

## Quick Reference

### Key File Locations

| What | Where |
|------|-------|
| Compiler entry | `packages/svelte/src/compiler/index.js` |
| Runtime client entry | `packages/svelte/src/internal/client/runtime.js` |
| Runtime server entry | `packages/svelte/src/internal/server/index.js` |
| All bitflag constants | `packages/svelte/src/constants.js` |
| All utility functions | `packages/svelte/src/utils.js` |
| Public type definitions | `packages/svelte/src/index.d.ts` |
| Package exports map | `packages/svelte/package.json` (`exports` field) |
| Rollup build config | `packages/svelte/rollup.config.js` |
| Monorepo workspace | `pnpm-workspace.yaml` |

### Dependency Summary

| Dependency | Role | Type |
|------------|------|------|
| `acorn` | JavaScript parser | Runtime |
| `@sveltejs/acorn-typescript` | TypeScript extension for acorn | Runtime |
| `magic-string` | String manipulation with source maps | Runtime |
| `@jridgewell/remapping` | Source map composition | Runtime |
| `@jridgewell/sourcemap-codec` | Source map encode/decode | Runtime |
| `zimmerframe` | AST walking utility | Runtime |
| `esrap` | AST → JS code printer | Runtime |
| `is-reference` | Check if AST node is a reference | Runtime |
| `locate-character` | Position lookup in strings | Runtime |
| `aria-query` | ARIA role/attribute database | Runtime |
| `axobject-query` | AXObject accessibility database | Runtime |
| `clsx` | Class name utility | Runtime |
| `devalue` | Serialize complex JS values (SSR) | Runtime |
| `esm-env` | BROWSER/SERVER constants | Runtime |
| `rollup` | Compiler bundle build | Dev |
| `vitest` | Unit testing | Dev |
| `@playwright/test` | E2E testing | Dev |
| `dts-buddy` | TypeScript declaration generation | Dev |
| `typescript` | Type checking | Dev |

---

_Generated May 2026 from sveltejs/svelte at fcaa8ce. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
