Claude
Skills
Sign in
Back

svelte-kit

Included with Lifetime
$97 forever

Svelte 5 and SvelteKit syntax expert. Use when working with .svelte files, runes syntax ($state, $derived, $effect), SvelteKit routing, SSR, or component design.

Design

What this skill does


# Svelte/SvelteKit Expert

Expert assistant for Svelte 5 runes syntax, SvelteKit routing, SSR/SSG strategies, and component design patterns.

## Mindset Shift (Svelte 4 → 5)

Default to Svelte 5 runes and modern SvelteKit conventions. The biggest mental shifts:

- **Stores → runes.** Reach for `$state`/`$derived` over `writable`/`$:`. `$state` objects/arrays are deeply reactive **proxies**.
- **`$effect` is a last resort, not a sync tool.** Derive with `$derived`; only use `$effect` for genuine side effects (DOM, logging, subscriptions).
- **Slots → snippets.** `{#snippet}` / `{@render}` replace `<slot>`.
- **`on:click` → `onclick`.** Events are plain attributes now (no colon).
- **`$app/stores` → `$app/state`.** Fine-grained, no `$` prefix needed.
- **`export let` → `$props()`** with `PageProps`/`LayoutProps` from `$types`.

## Thinking Process

When activated, follow this structured thinking approach to solve Svelte/SvelteKit problems:

### Step 1: Problem Classification

**Goal:** Understand what type of Svelte challenge this is.

**Key Questions to Ask:**
- Is this a reactivity problem? (state updates not reflecting, derived values)
- Is this a rendering problem? (SSR vs CSR, hydration mismatch)
- Is this a routing problem? (navigation, params, layouts)
- Is this a data loading problem? (load functions, form actions)
- Is this a component design problem? (props, slots, events)

**Decision Point:** Classify to select appropriate solutions:
- Reactivity → Check runes usage ($state, $derived, $effect)
- Rendering → Consider SSR/CSR implications
- Routing → Review SvelteKit conventions
- Data Loading → Differentiate +page.ts vs +page.server.ts
- Components → Apply composition patterns

### Step 2: Version and Context Check

**Goal:** Ensure solutions match the project's Svelte version.

**Key Questions to Ask:**
- Is this Svelte 5 (runes) or Svelte 4 (stores)?
- What SvelteKit version is in use?
- What rendering mode is configured? (SSR, SPA, SSG)

**Actions:**
1. Check `package.json` for svelte and @sveltejs/kit versions
2. Look for `svelte.config.js` adapter configuration
3. Note any prerender settings

**Version-Specific Syntax:**
| Concept | Svelte 4 | Svelte 5 |
|---------|----------|----------|
| Reactive state | `let x = 0` | `let x = $state(0)` |
| Derived | `$: doubled = x * 2` | `let doubled = $derived(x * 2)` |
| Effects | `$: console.log(x)` | `$effect(() => console.log(x))` |
| Props | `export let name` | `let { name } = $props()` |

**Decision Point:** Always default to Svelte 5 runes syntax unless explicitly working with Svelte 4.

### Step 3: SSR/CSR Analysis

**Goal:** Understand the rendering context and its implications.

**Thinking Framework:**
- "When does this code run?" (server, client, or both)
- "What data is available at each stage?"
- "Could this cause a hydration mismatch?"

**SSR Decision Matrix:**

| Code Location | Runs On | Use For |
|---------------|---------|---------|
| +page.server.ts | Server only | DB access, secrets, auth |
| +page.ts | Server + Client | Public API calls, URL-dependent data |
| +page.svelte | Server + Client | UI rendering |
| $effect() | Client only | DOM manipulation, subscriptions |

**Common SSR Pitfalls:**
- Browser APIs (window, document) in SSR context
- Different content between server and client render
- Accessing cookies/headers incorrectly

**SSR Safety Pattern:** guard browser-only APIs with `import { browser } from '$app/environment'`, and run DOM access inside `$effect(() => { if (browser) { /* ... */ } })` (effects are client-only).

### Step 4: Data Flow Design

**Goal:** Design correct data loading and mutation patterns.

**Thinking Framework:**
- "Where does this data come from?" (server, client, URL)
- "When should it be fetched?" (navigation, action, interval)
- "Who can access this data?" (public, authenticated, authorized)

**Load Function Selection:**

| Need | Use | Why |
|------|-----|-----|
| Access secrets/DB | +page.server.ts | Never exposed to client |
| Public API call | +page.ts | Runs on both, good for caching |
| SEO-critical data | +page.server.ts | Guaranteed in initial HTML |
| Client-side only | fetch in $effect | Avoid SSR overhead |

**Form Action Thinking:**
- "What mutation does this form perform?"
- "What validation is needed?"
- "What should happen on success/failure?"

**Load Rerun & Auth Implications:**
- Rerun loads with `invalidate(url)` / `invalidateAll()`; declare deps with `depends()`; opt out of tracking with `untrack()`.
- **Layout loads do not auto-rerun on client-side navigation.** For auth, prefer the `handle` hook or per-page server loads over a single root layout load.
- When an action changes auth, update `event.locals` so subsequent loads see the new state.
- Use `getRequestEvent()` (SvelteKit ≥ 2.20) in shared server functions to read `locals`/`url` without threading the event through params.

**Streaming:** return an unawaited promise from a server load and render it with `{#await}` for progressive data.

### Step 5: Reactivity Design

**Goal:** Apply correct reactivity patterns for the use case.

**Thinking Framework - Runes Selection:**

| Need | Rune | Example |
|------|------|---------|
| Mutable state | $state | `let count = $state(0)` |
| Computed value | $derived | `let double = $derived(count * 2)` |
| Side effects | $effect | `$effect(() => save(data))` |
| Component props | $props | `let { name } = $props()` |
| Two-way binding | $bindable | `let { value = $bindable() } = $props()` |

**Reactivity Rules:**
1. Only use `$state` for values that need to trigger updates
2. Use `$derived` for any computed values (not manual updates); keep derived expressions **pure** (no side effects). Use `$derived.by(() => { ... })` for multi-line logic.
3. Use `$effect` sparingly — **only for genuine side effects** (DOM, logging, subscriptions), never to synchronize/derive state. Return a teardown function for cleanup.
4. Never mutate `$derived` values to "fix" them with `$effect`. Derived values **can** be reassigned for optimistic UI and self-revert when dependencies change.

**Deep Reactivity & State Nuances:**
- `$state` objects/arrays are deeply reactive **proxies** — mutating nested fields triggers updates.
- **Never destructure** reactive state or props — it captures a snapshot and breaks reactivity. Access fields directly (`obj.x`) or via getters.
- `$state.raw(...)` — shallow/non-tracked state; reassign the whole value, don't mutate.
- `$state.snapshot(...)` — plain (non-proxy) copy for passing to external/non-Svelte APIs.
- Pass live state into functions via **getter functions** (`() => count`), not the bare variable.

**Effect Variants:** `$effect.pre` (run before DOM update, e.g. autoscroll), `$effect.tracking()` (is this in a reactive context?), `$effect.root` (manually-scoped, manual cleanup).

**Anti-Patterns to Avoid:**
```svelte
<script>
  // BAD: using $effect to derive/sync state
  let doubled = $state(0);
  $effect(() => { doubled = count * 2; }); // use $derived instead

  // BAD: destructuring reactive state/props (loses reactivity)
  let { user } = data;        // snapshot — won't update
  let { x, y } = $state({ x: 0, y: 0 });

  // BAD: mutating props
  let { count } = $props();
  count += 1;                 // props are read-only; use $bindable() for two-way
</script>
```

### Step 6: Component Design

**Goal:** Design reusable, composable components.

**Thinking Framework:**
- "What is the single responsibility of this component?"
- "What props does it need?"
- "How flexible should slot composition be?"

**Component Interface Design:**
```svelte
<script>
  // Required props
  let { title, items } = $props();

  // Optional props with defaults
  let { variant = 'default', disabled = false } = $props();

  // Callback props
  let { onClick = () => {} } = $props();

  // Bindable props for two-way binding
  let { value = $bindable() } = $props();
</script>
```

**Slot Patterns:**
- Default slot: Main content area
- Na
Files: 1
Size: 17.2 KB
Complexity: 20/100
Category: Design

Related in Design