Svelte
Reactivity is explicit, compiler-driven, and minimal-runtime. Every reactive declaration uses a $ rune. The
compiler transforms declarative code into surgical DOM updates -- no virtual DOM, no diffing, no hidden magic.
References contain extended examples, rationale, and edge cases for each topic.
References
- Runes — [
${CLAUDE_SKILL_DIR}/references/runes.md]: $state, $derived, $effect, $props, $bindable
details
- Components — [
${CLAUDE_SKILL_DIR}/references/components.md]: Snippets, events, context, special elements
- SvelteKit — [
${CLAUDE_SKILL_DIR}/references/sveltekit.md]: Routing, load functions, form actions, hooks, imports
Runes
$state
- Every mutable reactive value must use
$state or $state.raw. Plain let declarations are not reactive.
- Arrays and plain objects become deeply reactive proxies. Mutations trigger granular updates.
- Destructuring
$state objects breaks reactivity -- destructured values are snapshots, not live references.
- Use
$state on class fields or as first assignment in constructor. The compiler transforms these into getter/setter
pairs. Use arrow functions to preserve this in event handlers on classes.
$state.raw opts out of deep reactivity -- state can only be reassigned, not mutated. Use for large arrays/objects
you replace wholesale to avoid proxy overhead.
$state.snapshot(value) takes a static copy of a reactive proxy for external APIs that don't expect proxies (e.g.,
structuredClone, logging).
- Import reactive
Set, Map, Date, URL from svelte/reactivity when you need reactive built-in types.
Sharing State Across Modules
Cannot directly export reassignable $state. Two patterns:
- Object property (preferred): export
$state({ count: 0 }) as a const, mutate properties, export modifier
functions.
- Getter function: keep
$state private, export getCount() and increment().
Runes only work in .svelte and .svelte.js/.svelte.ts files.
$derived
- Use
$derived for all computed values -- never synchronize state with $effect.
$derived.by(() => { ... }) for complex derivations needing a function body.
- Only synchronously read values are tracked. Use
untrack to exempt specific reads.
- Derived values can be temporarily overridden (useful for optimistic UI) -- reverts to derived computation on next
dependency update.
- Destructured
$derived values are individually reactive.
- Push-pull reactivity: dependents are notified immediately (push) but only recalculated on read (pull). If new value is
referentially identical, downstream updates are skipped.
$effect
$effect is an escape hatch. Use only for side effects: DOM manipulation, analytics, third-party library calls,
timers.
- Return a cleanup function when acquiring resources (intervals, listeners).
- Only synchronously read values are tracked -- values read after
await or inside setTimeout are NOT tracked.
- Conditional reads: only values read in the last execution are dependencies.
- Runs only in the browser, after DOM updates.
$effect.pre runs before DOM updates -- use for pre-DOM manipulation like autoscrolling.
$effect.tracking() returns true if code is running inside a tracking context.
$effect.root(() => { ... }) creates a non-tracked scope for manual effect lifecycle control. Returns a destroy
function.
Never use $effect to synchronize state -- use $derived with callback event handlers or function bindings
instead.
$props
- Always destructure props:
let { name, count = 0 } = $props().
- Type with an interface in TypeScript:
let { name }: Props = $props().
- Renaming:
let { class: klass } = $props().
- Rest props:
let { a, b, ...rest } = $props().
- All props:
let props = $props().
- Unique ID:
$props.id() -- consistent across SSR/hydration.
- Props can be temporarily overridden by child. Do NOT mutate prop objects unless
$bindable. Use callback props to
communicate changes upward.
$bindable
- Marks a prop as two-way bindable:
let { value = $bindable() } = $props().
- Parent optionally uses
bind:value={variable}.
- Use sparingly -- overuse makes data flow unpredictable. Prefer callback props for most parent-child communication.
$inspect
- Development-only debugging rune. Re-runs when arguments change. Noop in production.
$inspect(count, message) logs when tracked values change.
$inspect(value).with((type, ...args) => { ... }) replaces default console.log with custom callback. Type is
"init" or "update".
$inspect.trace() traces which reactive state caused a re-execution. Must be first statement in a function body.
$host
Only available inside custom elements. Provides access to the host element for dispatching custom events.
Components
Structure Order
- Imports
- Props (
$props())
- State (
$state)
- Derived values (
$derived)
- Effects (
$effect, sparingly)
- Functions
- Markup (template)
- Styles (
<style>)
Naming
- Capitalize component names:
<MyComponent />. Required for dynamic rendering.
- Component names must be capitalized or use dot notation (
item.component).
- Components are dynamic by default --
<svelte:component> is unnecessary. Just use <Thing /> where Thing is a
reactive variable.
Events
- Use standard event attributes:
onclick={handler}, never on:click={handler}.
- Event attributes are case sensitive --
onclick listens to click, onClick listens to Click.
- No event modifiers -- call
event.preventDefault() / event.stopPropagation() in the handler. For capture, append to
event name: onclickcapture={...}.
- Callback props for component events -- pass functions as props:
let { onEvent } = $props(). Never use
createEventDispatcher.
- Event forwarding: accept callback props and spread them onto elements.
- Multiple handlers: combine in a single function (no duplicate attributes).
- Svelte uses event delegation for common events (
click, input, keydown) -- single listener at app root. When
manually dispatching events, set { bubbles: true }. Prefer on from svelte/events over raw addEventListener.
Snippets
- Use
{@render children?.()} for default content. Never use <slot />.
- Named snippets: declare with
{#snippet header()}...{/snippet} in parent, accept as props, render with
{@render header()}.
- Snippets with parameters pass data from child to parent:
{@render item(entry)} in child, {#snippet item(text)} in
parent.
- Optional snippets: use
{@render children?.()} or {#if children} with fallback.
- Snippets follow lexical scoping -- visible within their declaring block and children.
- Top-level snippets can be exported from
<script module> for cross-component use.
- Type snippets with
Snippet and Snippet<[ParamType]> from svelte.
Template Syntax
Control flow:
{#if} / {:else if} / {:else} / {/if} for conditional blocks.
{#each items as item, index (item.id)} with key expression for lists. Always provide a key for lists that can
change. :else renders when array is empty.
{#key value} destroys and recreates contents when value changes -- triggers entry transitions or resets component
state.
{#await promise} / {:then value} / {:catch error} for async. Short forms: {#await promise then value} skips
loading state.
Special tags:
{@html rawHtml} -- render raw HTML (escape user input to prevent XSS).
{@const x = expr} -- declare local constant inside a block scope.
{@debug var1, var2} -- trigger debugger when values change.
{@render snippet()} -- render a snippet.
{@attach action} -- attach an action to an element.
Text expressions: {expression} outputs stringified, escaped value. null and undefined are omitted.
Conditional classes: object syntax like clsx: class={{ cool, lame: !cool }}.
Context
setContext(key, value) / getContext(key) passes data through the component tree without prop drilling.
- Type-safe context: use
createContext<T>() from svelte which returns [getContext, setContext] pair.
- Do NOT reassign the context object -- mutate its properties instead.
- For SSR safety, prefer context over global module state.
- Pass functions into
setContext to maintain reactivity across boundaries.
Special Elements
<svelte:boundary> -- error boundary. Use {#snippet failed(error, reset)} for error UI and {#snippet pending()}
for loading state with await expressions.
<svelte:window> -- bind to window events and properties (bind:scrollY).
<svelte:head> -- insert elements into document.head (SEO meta tags, title).
<svelte:element this={tag}> -- render a dynamic HTML element.
<svelte:options> -- set compiler options (customElement, namespace).
Component Instantiation
Components are functions, not classes:
mount(Component, { target }) for client-side mounting.
unmount(app) to destroy.
hydrate instead of mount for server-rendered HTML.
State Management
- No shared module state on the server -- module-level
$state is shared across requests during SSR. Use context or
event.locals instead.
- Return data from
load, don't write to globals. No side effects in load functions.
- Context for SSR-safe shared state --
setContext/getContext for data that must not leak between requests.
- Use
$derived for reactive computed values in components -- plain assignments in <script> run once, not reactively.
- Store filter/sort state in URL for survival across reload.
- Use snapshots for ephemeral UI state that should survive back/forward navigation.
File Conventions
.svelte.js / .svelte.ts for reactive modules -- runes only work in .svelte and .svelte.js/.svelte.ts files.
$lib for shared code -- import from $lib/ instead of relative paths climbing multiple levels.
SvelteKit
Route Files
+page.svelte — Page component (receives data from load)
+page.js — Universal load (server + browser)
+page.server.js — Server-only load + form actions
+layout.svelte — Layout wrapper (must render {@render children()})
+layout.js — Layout universal load
+layout.server.js — Layout server load
+error.svelte — Error boundary
+server.js — API endpoint (GET, POST, etc.)
Key rules: all files can run on the server. All run on the client except +server files. +layout and +error apply
to subdirectories too.
Load Functions
Decision tree:
| Need |
Use |
| Database, private keys |
+page.server.js (PageServerLoad) |
| Non-serializable return values |
+page.js (PageLoad) |
| External API, no secrets |
+page.js (PageLoad) |
| Both |
Both (server data flows to universal) |
Universal vs server:
| Aspect |
Universal (+page.js) |
Server (+page.server.js) |
| Runs on |
Server (SSR) + Browser |
Server only |
| Access |
params, url, fetch |
+ cookies, locals, request |
| Returns |
Any value (classes, components) |
Serializable data only |
- Use the provided
fetch, not global fetch -- inherits cookies, makes relative requests work on server, bypasses
HTTP overhead for internal requests.
- Export page options from
+page.js: prerender, ssr, csr.
- Layout load data is available to all child pages.
- Stream non-essential data by returning un-awaited promises.
- SvelteKit tracks load dependencies and only reruns when:
params change, url properties change, parent() was
called and parent reran, or invalidate()/invalidateAll() called.
- Use
error() and redirect() from @sveltejs/kit for error and redirect responses.
Form Actions
Server-only POST handlers in +page.server.js. Work without JavaScript.
- Default action:
export const actions = { default: async ({ request }) => { ... } }.
- Named actions:
action="?/login" on form, multiple actions in the actions object.
- Validation: return
fail(400, { field, missing: true }) from action. Access via form prop in the page component.
- Progressive enhancement: add
use:enhance from $app/forms for JS-enhanced submission without full page reload.
API Routes
Export HTTP verb handlers from +server.js: GET, POST, PUT, PATCH, DELETE. Return json() or
new Response().
Hooks
Server hooks (src/hooks.server.js):
handle({ event, resolve }) -- intercept every request. Set event.locals, modify response headers.
handleFetch -- modify server-side fetch calls.
handleError -- log and sanitize unexpected errors.
init -- run once at server startup.
Client hooks (src/hooks.client.js):
handleError -- client-side error handling.
Universal hooks (src/hooks.js):
reroute -- rewrite URLs before routing.
transport -- serialize/deserialize custom types across server/client boundary.
Key Imports
Most-used modules: $app/navigation (goto, invalidate), $app/state (page, navigating), $app/forms
(enhance), $env/static/private and $env/static/public for environment variables, $lib for shared code. Full
imports table in ${CLAUDE_SKILL_DIR}/references/sveltekit.md.
Performance
- Use server
load functions to avoid browser-to-API waterfalls.
- Stream non-essential data with un-awaited promises.
- Use
$derived instead of $effect for computed values.
- Use link preloading (default on
<body>).
- Minimize third-party scripts.
- Use
@sveltejs/enhanced-img for image optimization.
- Use dynamic
import() for conditional code.
- Deploy frontend near backend to minimize latency.
Application
When writing Svelte code:
- Apply all conventions silently -- don't narrate each rule.
- Always use runes, event attributes, and snippets.
- If an existing codebase uses outdated patterns, follow the codebase and flag the divergence once.
- Type props with interfaces in TypeScript projects.
When reviewing Svelte code:
- Cite the specific violation and show the fix inline.
- Don't lecture -- state what's wrong and how to fix it.
Integration
This skill provides Svelte-specific conventions. The coding skill governs workflow; for TypeScript projects, the
typescript skill handles language-level choices; for CSS concerns, the css skill handles styling conventions.
1---2name: svelte3description: Svelte runes-first reactivity and SvelteKit fullstack conventions. Invoke whenever task involves any interaction with Svelte code — writing, reviewing, refactoring, debugging, or understanding .svelte, .svelte.js, .svelte.ts files and SvelteKit projects.4---56# Svelte78**Reactivity is explicit, compiler-driven, and minimal-runtime.** Every reactive declaration uses a `$` rune. The9compiler transforms declarative code into surgical DOM updates -- no virtual DOM, no diffing, no hidden magic.10References contain extended examples, rationale, and edge cases for each topic.1112## References1314- **Runes** — [`${CLAUDE_SKILL_DIR}/references/runes.md`]: `$state`, `$derived`, `$effect`, `$props`, `$bindable`15 details16- **Components** — [`${CLAUDE_SKILL_DIR}/references/components.md`]: Snippets, events, context, special elements17- **SvelteKit** — [`${CLAUDE_SKILL_DIR}/references/sveltekit.md`]: Routing, load functions, form actions, hooks, imports1819## Runes2021### `$state`2223- Every mutable reactive value must use `$state` or `$state.raw`. Plain `let` declarations are not reactive.24- Arrays and plain objects become deeply reactive proxies. Mutations trigger granular updates.25- Destructuring `$state` objects breaks reactivity -- destructured values are snapshots, not live references.26- Use `$state` on class fields or as first assignment in constructor. The compiler transforms these into getter/setter27 pairs. Use arrow functions to preserve `this` in event handlers on classes.28- `$state.raw` opts out of deep reactivity -- state can only be reassigned, not mutated. Use for large arrays/objects29 you replace wholesale to avoid proxy overhead.30- `$state.snapshot(value)` takes a static copy of a reactive proxy for external APIs that don't expect proxies (e.g.,31 `structuredClone`, logging).32- Import reactive `Set`, `Map`, `Date`, `URL` from `svelte/reactivity` when you need reactive built-in types.3334### Sharing State Across Modules3536Cannot directly export reassignable `$state`. Two patterns:3738- **Object property (preferred):** export `$state({ count: 0 })` as a const, mutate properties, export modifier39 functions.40- **Getter function:** keep `$state` private, export `getCount()` and `increment()`.4142Runes only work in `.svelte` and `.svelte.js`/`.svelte.ts` files.4344### `$derived`4546- Use `$derived` for all computed values -- never synchronize state with `$effect`.47- `$derived.by(() => { ... })` for complex derivations needing a function body.48- Only synchronously read values are tracked. Use `untrack` to exempt specific reads.49- Derived values can be temporarily overridden (useful for optimistic UI) -- reverts to derived computation on next50 dependency update.51- Destructured `$derived` values are individually reactive.52- Push-pull reactivity: dependents are notified immediately (push) but only recalculated on read (pull). If new value is53 referentially identical, downstream updates are skipped.5455### `$effect`5657- `$effect` is an escape hatch. Use only for side effects: DOM manipulation, analytics, third-party library calls,58 timers.59- Return a cleanup function when acquiring resources (intervals, listeners).60- Only synchronously read values are tracked -- values read after `await` or inside `setTimeout` are NOT tracked.61- Conditional reads: only values read in the last execution are dependencies.62- Runs only in the browser, after DOM updates.63- `$effect.pre` runs before DOM updates -- use for pre-DOM manipulation like autoscrolling.64- `$effect.tracking()` returns `true` if code is running inside a tracking context.65- `$effect.root(() => { ... })` creates a non-tracked scope for manual effect lifecycle control. Returns a destroy66 function.6768**Never use `$effect` to synchronize state** -- use `$derived` with callback event handlers or function bindings69instead.7071### `$props`7273- Always destructure props: `let { name, count = 0 } = $props()`.74- Type with an interface in TypeScript: `let { name }: Props = $props()`.75- Renaming: `let { class: klass } = $props()`.76- Rest props: `let { a, b, ...rest } = $props()`.77- All props: `let props = $props()`.78- Unique ID: `$props.id()` -- consistent across SSR/hydration.79- Props can be temporarily overridden by child. Do NOT mutate prop objects unless `$bindable`. Use callback props to80 communicate changes upward.8182### `$bindable`8384- Marks a prop as two-way bindable: `let { value = $bindable() } = $props()`.85- Parent optionally uses `bind:value={variable}`.86- Use sparingly -- overuse makes data flow unpredictable. Prefer callback props for most parent-child communication.8788### `$inspect`8990- Development-only debugging rune. Re-runs when arguments change. Noop in production.91- `$inspect(count, message)` logs when tracked values change.92- `$inspect(value).with((type, ...args) => { ... })` replaces default `console.log` with custom callback. Type is93 `"init"` or `"update"`.94- `$inspect.trace()` traces which reactive state caused a re-execution. Must be first statement in a function body.9596### `$host`9798Only available inside custom elements. Provides access to the host element for dispatching custom events.99100## Components101102### Structure Order1031041. Imports1052. Props (`$props()`)1063. State (`$state`)1074. Derived values (`$derived`)1085. Effects (`$effect`, sparingly)1096. Functions1107. Markup (template)1118. Styles (`<style>`)112113### Naming114115- Capitalize component names: `<MyComponent />`. Required for dynamic rendering.116- Component names must be capitalized or use dot notation (`item.component`).117- Components are dynamic by default -- `<svelte:component>` is unnecessary. Just use `<Thing />` where `Thing` is a118 reactive variable.119120### Events121122- Use standard event attributes: `onclick={handler}`, never `on:click={handler}`.123- Event attributes are case sensitive -- `onclick` listens to `click`, `onClick` listens to `Click`.124- No event modifiers -- call `event.preventDefault()` / `event.stopPropagation()` in the handler. For capture, append to125 event name: `onclickcapture={...}`.126- Callback props for component events -- pass functions as props: `let { onEvent } = $props()`. Never use127 `createEventDispatcher`.128- Event forwarding: accept callback props and spread them onto elements.129- Multiple handlers: combine in a single function (no duplicate attributes).130- Svelte uses event delegation for common events (`click`, `input`, `keydown`) -- single listener at app root. When131 manually dispatching events, set `{ bubbles: true }`. Prefer `on` from `svelte/events` over raw `addEventListener`.132133### Snippets134135- Use `{@render children?.()}` for default content. Never use `<slot />`.136- Named snippets: declare with `{#snippet header()}...{/snippet}` in parent, accept as props, render with137 `{@render header()}`.138- Snippets with parameters pass data from child to parent: `{@render item(entry)}` in child, `{#snippet item(text)}` in139 parent.140- Optional snippets: use `{@render children?.()}` or `{#if children}` with fallback.141- Snippets follow lexical scoping -- visible within their declaring block and children.142- Top-level snippets can be exported from `<script module>` for cross-component use.143- Type snippets with `Snippet` and `Snippet<[ParamType]>` from `svelte`.144145### Template Syntax146147**Control flow:**148149- `{#if}` / `{:else if}` / `{:else}` / `{/if}` for conditional blocks.150- `{#each items as item, index (item.id)}` with key expression for lists. Always provide a key for lists that can151 change. `:else` renders when array is empty.152- `{#key value}` destroys and recreates contents when value changes -- triggers entry transitions or resets component153 state.154- `{#await promise}` / `{:then value}` / `{:catch error}` for async. Short forms: `{#await promise then value}` skips155 loading state.156157**Special tags:**158159- `{@html rawHtml}` -- render raw HTML (escape user input to prevent XSS).160- `{@const x = expr}` -- declare local constant inside a block scope.161- `{@debug var1, var2}` -- trigger debugger when values change.162- `{@render snippet()}` -- render a snippet.163- `{@attach action}` -- attach an action to an element.164165**Text expressions:** `{expression}` outputs stringified, escaped value. `null` and `undefined` are omitted.166167**Conditional classes:** object syntax like `clsx`: `class={{ cool, lame: !cool }}`.168169### Context170171- `setContext(key, value)` / `getContext(key)` passes data through the component tree without prop drilling.172- Type-safe context: use `createContext<T>()` from `svelte` which returns `[getContext, setContext]` pair.173- Do NOT reassign the context object -- mutate its properties instead.174- For SSR safety, prefer context over global module state.175- Pass functions into `setContext` to maintain reactivity across boundaries.176177### Special Elements178179- `<svelte:boundary>` -- error boundary. Use `{#snippet failed(error, reset)}` for error UI and `{#snippet pending()}`180 for loading state with `await` expressions.181- `<svelte:window>` -- bind to window events and properties (`bind:scrollY`).182- `<svelte:head>` -- insert elements into `document.head` (SEO meta tags, title).183- `<svelte:element this={tag}>` -- render a dynamic HTML element.184- `<svelte:options>` -- set compiler options (`customElement`, `namespace`).185186### Component Instantiation187188Components are functions, not classes:189190- `mount(Component, { target })` for client-side mounting.191- `unmount(app)` to destroy.192- `hydrate` instead of `mount` for server-rendered HTML.193194## State Management195196- No shared module state on the server -- module-level `$state` is shared across requests during SSR. Use context or197 `event.locals` instead.198- Return data from `load`, don't write to globals. No side effects in load functions.199- Context for SSR-safe shared state -- `setContext`/`getContext` for data that must not leak between requests.200- Use `$derived` for reactive computed values in components -- plain assignments in `<script>` run once, not reactively.201- Store filter/sort state in URL for survival across reload.202- Use snapshots for ephemeral UI state that should survive back/forward navigation.203204## File Conventions205206- `.svelte.js` / `.svelte.ts` for reactive modules -- runes only work in `.svelte` and `.svelte.js`/`.svelte.ts` files.207- `$lib` for shared code -- import from `$lib/` instead of relative paths climbing multiple levels.208209## SvelteKit210211### Route Files212213- `+page.svelte` — Page component (receives `data` from load)214- `+page.js` — Universal load (server + browser)215- `+page.server.js` — Server-only load + form actions216- `+layout.svelte` — Layout wrapper (must render `{@render children()}`)217- `+layout.js` — Layout universal load218- `+layout.server.js` — Layout server load219- `+error.svelte` — Error boundary220- `+server.js` — API endpoint (GET, POST, etc.)221222Key rules: all files can run on the server. All run on the client except `+server` files. `+layout` and `+error` apply223to subdirectories too.224225### Load Functions226227**Decision tree:**228229| Need | Use |230| ------------------------------ | ------------------------------------- |231| Database, private keys | `+page.server.js` (PageServerLoad) |232| Non-serializable return values | `+page.js` (PageLoad) |233| External API, no secrets | `+page.js` (PageLoad) |234| Both | Both (server data flows to universal) |235236**Universal vs server:**237238| Aspect | Universal (+page.js) | Server (+page.server.js) |239| ------- | ------------------------------- | -------------------------------- |240| Runs on | Server (SSR) + Browser | Server only |241| Access | `params`, `url`, `fetch` | + `cookies`, `locals`, `request` |242| Returns | Any value (classes, components) | Serializable data only |243244- Use the provided `fetch`, not global `fetch` -- inherits cookies, makes relative requests work on server, bypasses245 HTTP overhead for internal requests.246- Export page options from `+page.js`: `prerender`, `ssr`, `csr`.247- Layout load data is available to all child pages.248- Stream non-essential data by returning un-awaited promises.249- SvelteKit tracks load dependencies and only reruns when: `params` change, `url` properties change, `parent()` was250 called and parent reran, or `invalidate()`/`invalidateAll()` called.251- Use `error()` and `redirect()` from `@sveltejs/kit` for error and redirect responses.252253### Form Actions254255Server-only POST handlers in `+page.server.js`. Work without JavaScript.256257- Default action: `export const actions = { default: async ({ request }) => { ... } }`.258- Named actions: `action="?/login"` on form, multiple actions in the `actions` object.259- Validation: return `fail(400, { field, missing: true })` from action. Access via `form` prop in the page component.260- Progressive enhancement: add `use:enhance` from `$app/forms` for JS-enhanced submission without full page reload.261262### API Routes263264Export HTTP verb handlers from `+server.js`: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`. Return `json()` or265`new Response()`.266267### Hooks268269**Server hooks** (`src/hooks.server.js`):270271- `handle({ event, resolve })` -- intercept every request. Set `event.locals`, modify response headers.272- `handleFetch` -- modify server-side fetch calls.273- `handleError` -- log and sanitize unexpected errors.274- `init` -- run once at server startup.275276**Client hooks** (`src/hooks.client.js`):277278- `handleError` -- client-side error handling.279280**Universal hooks** (`src/hooks.js`):281282- `reroute` -- rewrite URLs before routing.283- `transport` -- serialize/deserialize custom types across server/client boundary.284285### Key Imports286287Most-used modules: `$app/navigation` (`goto`, `invalidate`), `$app/state` (`page`, `navigating`), `$app/forms`288(`enhance`), `$env/static/private` and `$env/static/public` for environment variables, `$lib` for shared code. Full289imports table in `${CLAUDE_SKILL_DIR}/references/sveltekit.md`.290291### Performance292293- Use server `load` functions to avoid browser-to-API waterfalls.294- Stream non-essential data with un-awaited promises.295- Use `$derived` instead of `$effect` for computed values.296- Use link preloading (default on `<body>`).297- Minimize third-party scripts.298- Use `@sveltejs/enhanced-img` for image optimization.299- Use dynamic `import()` for conditional code.300- Deploy frontend near backend to minimize latency.301302## Application303304When **writing** Svelte code:305306- Apply all conventions silently -- don't narrate each rule.307- Always use runes, event attributes, and snippets.308- If an existing codebase uses outdated patterns, follow the codebase and flag the divergence once.309- Type props with interfaces in TypeScript projects.310311When **reviewing** Svelte code:312313- Cite the specific violation and show the fix inline.314- Don't lecture -- state what's wrong and how to fix it.315316## Integration317318This skill provides Svelte-specific conventions. The coding skill governs workflow; for TypeScript projects, the319typescript skill handles language-level choices; for CSS concerns, the css skill handles styling conventions.