Help us improve
Share bugs, ideas, or general feedback.
From flow
Provides examples for Svelte 5 runes ($state, $derived), bindable props, snippets, SvelteKit load functions and form actions, plus Svelte 4 migration guidance.
npx claudepluginhub cofin/flow --plugin flowHow this skill is triggered — by the user, by Claude, or both
Slash command
/flow:svelteThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
<workflow>
Enforces Svelte 5 best practices in SvelteKit: runes ($state, $derived, $effect), $props(), $bindable(), load functions, form actions, and SSR patterns to fix outdated Svelte 4 code.
Provides Svelte 5.0 knowledge patch on runes ($state, $derived, $effect, $props), snippets replacing slots, callback props for events, mount/hydrate API. Auto-loads for Svelte tasks.
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.
Share bugs, ideas, or general feedback.
<script lang="ts">
interface Props {
title: string;
items: Item[];
onselect?: (item: Item) => void;
}
let { title, items, onselect }: Props = $props();
let selected = $state<Item | null>(null);
let count = $derived(items.length);
function handleSelect(item: Item) {
selected = item;
onselect?.(item);
}
$effect(() => {
console.log('Selected changed:', selected);
});
</script>
<div>
<h2>{title} ({count})</h2>
<ul>
{#each items as item (item.id)}
<li onclick={() => handleSelect(item)}>
{item.name}
</li>
{/each}
</ul>
</div>
// stores/counter.svelte.ts
class Counter {
count = $state(0);
doubled = $derived(this.count * 2);
increment() {
this.count++;
}
decrement() {
this.count--;
}
}
export const counter = new Counter();
<script lang="ts">
let { value = $bindable('') }: { value: string } = $props();
</script>
<input bind:value />
<script lang="ts">
import type { Snippet } from 'svelte';
interface Props {
header: Snippet;
children: Snippet;
footer?: Snippet<[{ count: number }]>;
}
let { header, children, footer }: Props = $props();
let count = $state(0);
</script>
<div class="card">
<header>{@render header()}</header>
<main>{@render children()}</main>
{#if footer}
<footer>{@render footer({ count })}</footer>
{/if}
</div>
// +page.server.ts
import type { PageServerLoad, Actions } from './$types';
export const load: PageServerLoad = async ({ params, fetch }) => {
const res = await fetch(`/api/items/${params.id}`);
if (!res.ok) throw error(404, 'Not found');
return {
item: await res.json()
};
};
export const actions: Actions = {
update: async ({ request, params }) => {
const data = await request.formData();
await updateItem(params.id, data);
return { success: true };
}
};
<script lang="ts">
import { enhance } from '$app/forms';
import type { ActionData } from './$types';
let { form }: { form: ActionData } = $props();
</script>
<form method="POST" action="?/update" use:enhance>
<input name="title" required />
<button type="submit">Save</button>
{#if form?.success}
<p>Saved!</p>
{/if}
</form>
| Svelte 4 | Svelte 5 |
|---|---|
export let prop | let { prop } = $props() |
$: derived | $derived(expr) |
$: { effect } | $effect(() => { }) |
<slot> | {@render children()} |
on:click | onclick |
bind:this | Still bind:this |
$state over stores for local state$derived for computed values$effect.pre for DOM measurements$state for reactive variables and $derived for computed logic. Avoid legacy Svelte 4 store patterns for local state.<slot> as it is deprecated in the new version.<script lang="ts"> to ensure type safety for props and event handlers.$effect for simple state updates -- Use $derived whenever possible to keep reactivity declarative. $effect should only be used for side effects (e.g., DOM interactions).$bindable() only when necessary -- Two-way binding should be used sparingly; prefer one-way data flow via props and callbacks where possible.
$state, $derived, $props)<slot> tags are used; snippets rendering is verified$effect is not misused for logic that can be handled by $derivedonclick instead of on:click)$bindable() rune