agentskills.codes
SV

sveltekit-latest

Quick-reference for SvelteKit + Svelte 5 development (Feb 2026)

Install

mkdir -p .claude/skills/sveltekit-latest && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16281" && unzip -o skill.zip -d .claude/skills/sveltekit-latest && rm skill.zip

Installs to .claude/skills/sveltekit-latest

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Quick-reference for SvelteKit + Svelte 5 development (Feb 2026)
63 charsno explicit “when” trigger

About this skill

SvelteKit + Svelte 5 Quick Reference (February 2026)

Current Versions

PackageVersionNotes
Svelte~5.50.xSvelte 5 is the current stable. Svelte 4 is legacy.
SvelteKit~2.50.xSvelteKit 2 is current stable. SvelteKit 1 is legacy.
sv (CLI)latestReplaces create-svelte. Use npx sv for all scaffolding.

Scaffolding a New Project

# Current recommended command (npm create svelte@latest is DEPRECATED)
npx sv create my-app
cd my-app
npm install
npm run dev

sv create options

FlagPurpose
--template minimal|demo|libraryProject template
--types ts|jsdoc|--no-typesTypeScript config
--add [add-ons...]Install add-ons (see below)
--no-add-onsSkip interactive add-on prompt
--install npm|pnpm|yarn|bun|denoPackage manager

Available add-ons

drizzle, eslint, better-auth, tailwindcss, prettier, vitest, playwright, storybook, mdsvex, paraglide, sveltekit-adapter, mcp, devtools-json

TypeScript Setup

TypeScript is built-in. Select "ts" when prompted by npx sv create, or pass --types ts. No extra configuration needed.

  • Use <script lang="ts"> in .svelte files
  • Types are auto-generated on npm run dev or npx svelte-kit sync
  • Required tsconfig options (set automatically): verbatimModuleSyntax: true, isolatedModules: true, noEmit: true
  • .svelte.ts files for reactive modules (replaces .ts when you need runes)

Svelte 5 Runes (Core Reactivity)

Runes replace Svelte 4's implicit reactivity (let, $:) with explicit, portable primitives.

$state -- Reactive State

<script>
  let count = $state(0);           // primitive
  let todos = $state([]);           // deep reactive proxy (arrays/objects)
</script>
<button onclick={() => count++}>{count}</button>
  • Deeply reactive: mutations to nested objects/arrays are tracked automatically
  • Class fields: done = $state(false); inside class bodies

$state.raw -- Non-reactive (reassign-only)

let items = $state.raw([1, 2, 3]);
// items.push(4)  -- NO EFFECT (not reactive)
items = [...items, 4]; // works (reassignment)

Use for large collections you never mutate in place. Better performance.

$state.snapshot -- Static copy

let data = $state({ count: 0 });
console.log($state.snapshot(data)); // plain object, no proxy

Use when passing state to external libraries or structuredClone.

$derived -- Computed Values

let count = $state(0);
const doubled = $derived(count * 2);

$derived.by -- Complex derivations

const filtered = $derived.by(() => {
  return items.filter(item => item.active);
});

$derived(expr) is equivalent to $derived.by(() => expr).

$effect -- Side Effects

$effect(() => {
  // Runs on mount and whenever dependencies change
  // Dependencies are auto-tracked
  console.log(`count is ${count}`);

  // Optional cleanup (returned function runs before re-execution)
  return () => { /* cleanup */ };
});

$effect.pre -- Before DOM update

$effect.pre(() => {
  // Runs before DOM is updated. Rare use case.
});

Rule of thumb: $derived for values, $effect for actions/side effects.

$props -- Component Props

<script>
  // Replaces "export let"
  let { name, count = 0, class: klass, ...rest } = $props();
</script>
  • Destructure with defaults, renaming, and rest props
  • Props are NOT bindable by default (see $bindable)

$bindable -- Two-way Binding

<script>
  let { value = $bindable('default') } = $props();
</script>

Parent can then use bind:value={something}.

$inspect -- Debug

$inspect(count); // logs to console whenever count changes (dev only, stripped in prod)

Snippets (Replace Slots)

Slots are deprecated. Use snippets and {@render} instead.

Default content (children)

<!-- Parent -->
<Card>
  <p>This becomes the children snippet</p>
</Card>

<!-- Card.svelte -->
<script>
  let { children } = $props();
</script>
<div class="card">
  {@render children?.()}
</div>

Named snippets

<!-- Parent -->
<Card>
  {#snippet header()}
    <h2>Title</h2>
  {/snippet}
  {#snippet footer()}
    <p>Footer</p>
  {/snippet}
  <p>Default children content</p>
</Card>

<!-- Card.svelte -->
<script>
  let { header, footer, children } = $props();
</script>
<div class="card">
  {@render header?.()}
  {@render children?.()}
  {@render footer?.()}
</div>

Snippets with parameters

<!-- Parent -->
<List items={users}>
  {#snippet item(user)}
    <span>{user.name}</span>
  {/snippet}
</List>

<!-- List.svelte -->
<script>
  let { items, item } = $props();
</script>
{#each items as entry}
  {@render item(entry)}
{/each}

Event Handling Changes

DOM events: remove the colon

<!-- Svelte 4 -->
<button on:click={handler}>Click</button>
<input on:input={handler} />

<!-- Svelte 5 -->
<button onclick={handler}>Click</button>
<input oninput={handler} />

Component events: callback props replace createEventDispatcher

<!-- Svelte 4 child -->
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
</script>
<button on:click={() => dispatch('submit', data)}>Submit</button>

<!-- Svelte 5 child -->
<script>
  let { onsubmit } = $props();
</script>
<button onclick={() => onsubmit(data)}>Submit</button>

Event modifiers are gone

Replace on:click|preventDefault with explicit calls:

<button onclick={(e) => { e.preventDefault(); handler(e); }}>Click</button>

Component Mounting (Programmatic)

// Svelte 4
const app = new App({ target: document.getElementById('app') });

// Svelte 5
import { mount, unmount } from 'svelte';
const app = mount(App, { target: document.getElementById('app') });
// later: unmount(app);

Cross-Module Reactive State (.svelte.ts files)

// counter.svelte.ts
let count = $state(0);

// Cannot export reassignable $state directly. Two patterns:

// Pattern 1: Export object (mutate properties)
export const counter = $state({ count: 0 });
export function increment() { counter.count++; }

// Pattern 2: Export getter functions
export function getCount() { return count; }
export function increment() { count++; }

SSR caveat: Module-scoped $state is a singleton shared across SSR requests. Always reset at render start. See "SSR Behavior for Module-Scoped State" below.

SSR Behavior for Module-Scoped State

What runs during SSR vs CSR

ContextSSRCSR
Top-level <script> codeYESYES
$state initializationYESYES
$derived / $derived.byCompiled as IIFE (computed once at module init)Reactive (recomputes on dependency change)
$effect / $effect.preNOYES
onMountNOYES
Template expressionsYESYES

The $derived SSR trap

$derived.by(() => ...) compiles to const x = (() => ...)() during SSR -- an immediately-invoked function that runs once at module initialization, not reactively. If module-scoped $state is set after the derived is initialized, the derived will NOT reflect the updated values.

Broken pattern:

// store.svelte.ts
let page = $state('');
const snapshot = $derived.by(() => ({ page })); // Frozen at init during SSR!
function setPage(p) { page = p; }

Working pattern:

// store.svelte.ts
let page = $state('');
function buildSnapshot() { return { page }; } // Fresh read every call
export const store = {
  get snapshot() { return buildSnapshot(); }, // Works in both SSR and CSR
  setPage(p) { page = p; },
};

During CSR, reading $state variables inside a getter called from a template still triggers Svelte 5's fine-grained reactivity tracking.

SSR baseline pattern for layouts/pages

To populate state during SSR, call setters at the top level of <script> blocks (not in $effect or onMount). Use $effect for client-side reactive updates:

<script>
  import { page } from '$app/stores';
  import { myStore } from '$lib/stores/my.svelte';

  let { data } = $props();

  // SSR + CSR: runs on every render
  myStore.setPage(data.title);

  // CSR only: reactive updates on navigation
  $effect(() => {
    myStore.setPage(data.title);
  });
</script>

Avoiding state_referenced_locally warnings

When you need $derived values for SSR baseline code, DON'T read the $derived at top level. Instead, compute the value directly from the source:

<!-- BAD: warns because $derived is read outside reactive context -->
<script>
  let isAdmin = $derived(data.user?.role === 'admin');
  if (isAdmin) { store.setAuth({...}); } // Warning!
</script>

<!-- GOOD: compute from source directly -->
<script>
  let isAdmin = $derived(data.user?.role === 'admin');
  // SSR baseline: use source data, not $derived
  if (data.user?.role === 'admin') { store.setAuth({...}); }
  // $effect for CSR reactivity uses $derived normally
  $effect(() => { if (isAdmin) { store.setAuth({...}); } });
</script>

Module-scoped $state and SSR safety

Module-scoped $state is shared across all SSR requests (it's a singleton). SvelteKit SSR is synchronous per-request, so call reset() at the top of the root layout to prevent cross-request pollution:

<!-- +layout.svelte (root) -->
<script>
  import { myStore } from '$lib/stores/my.svelte';
  myStore.reset(); // Clear state before each render
</script>

SvelteKit 2 Key Differences from SvelteKit 1

  • error() and redirect() no longer need to be thrown -- just call them
  • cookies.set/delete/serialize require explicit path parameter
  • Import vitePreprocess from @sveltejs/vite-plugin-svelte (not from SvelteKit)
  • resolvePath replaced by resolveRoute from $app/paths
  • Paths are consistently relati

Content truncated.

More by diegosouzapw

View all by diegosouzapw

helm-chart-scaffolding-v2

diegosouzapw

Helm Chart Scaffolding workflow skill. Use this skill when the user needs Comprehensive guidance for creating, organizing, and managing Helm charts for packaging and deploying Kubernetes applications and the operator should preserve the upstream workflow, copied support files, and provenance before

00

cc-skill-coding-standards-v2

diegosouzapw

Coding Standards & Best Practices workflow skill. Use this skill when the user needs Universal coding standards, best practices, and patterns for TypeScript, JavaScript, React, and Node.js development and the operator should preserve the upstream workflow, copied support files, and provenance before

00

worktree-setup

diegosouzapw

Automatically invoked after `git worktree add` to create data/shared symlink and data/local directory. Required before starting work in any new worktree.

00

parsehub-automation

diegosouzapw

Automate Parsehub tasks via Rube MCP (Composio). Always search tools first for current schemas.

00

signalwire-agents-sdk

diegosouzapw

Expert assistance for building SignalWire AI Agents in Python. Automatically activates when working with AgentBase, SWAIG functions, skills, SWML, voice configuration, DataMap, or any signalwire_agents code. Provides patterns, best practices, and complete working examples.

00

agent-sales-engineer

diegosouzapw

Expert sales engineer specializing in technical pre-sales, solution architecture, and proof of concepts. Masters technical demonstrations, competitive positioning, and translating complex technology into business value for prospects and customers.

00

Search skills

Search the agent skills registry