How to use
- Copy the installation command and review the source package before installing it in your own agent environment.
- Check the source document for required tools, credentials and supported hosts.
- Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/joshuadavidthomas/agent-skills --skill svelte5Before you start
- Installation does not include a model subscription, API allowance or permission to access your files.
- Repository stars and installation counts describe activity, not an independent quality or security test.
Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.
Think in Svelte 5
You already know Svelte syntax. This skill changes your defaults — what you reach for first when designing a component, placing state, modeling reactivity, and reviewing UI code.
The core failure mode is Svelte that compiles but thinks like React, Vue, or Svelte 4 — effects standing in for derived values and events, props mirrored into state, global stores by reflex, two-way binding as the default, clickable divs, Svelte 4 component APIs in new code.
The component is a small reactive program with visible dependencies. Keep dataflow direct, state ownership obvious, and markup semantic; let the compiler and the DOM do the work.
This skill is the general-purpose entry point for Svelte component review; for SvelteKit-level concerns, also use sveltekit (see Cross-References).
Treat these as strong defaults, not rigid laws: when unsure, choose the approach that makes ownership, dependencies, and user semantics more explicit.
How Svelte Thinks
Make reactivity visible
1. Reactivity is read-tracked. A $derived/$effect depends on what it reads while running; if one reruns unexpectedly, inspect its reads, not a dependency array. See references/read-tracked-reactivity.md.
2. Derived state is `$derived`, not `$effect`. Pure functions of other state get derived; effects are for side effects, not keeping variables in sync. See references/effect-driven-state.md.
<!-- ❌ effect writing derived state -->
let doubled = $state(0);
$effect(() => { doubled = count * 2; });
<!-- ✅ derive it -->
let doubled = $derived(count * 2);3. Effects are escape hatches. Before $effect, check for a derived value, an event handler, or a bind: getter/setter. Use it only to touch the outside world — subscriptions, timers, observers, imperative APIs, logging — and return cleanup.
4. Runes are statically analyzable. Compiler syntax, not runtime hooks — reusable state becomes .svelte.ts classes and factories, not custom hooks. See references/static-runes.md.
5. `$state` is a deep proxy, not React state. Mutate what changed in local arrays and objects; skip the immutable-update ceremony. See references/deep-state-without-immutable-ceremony.md.
Put state where ownership is clearest
6. State has an owner. Local interaction state → component; reusable behavior → .svelte.ts class; descendant-shared → context; stores only for the store contract, not every changing value. See references/state-ownership.md.
7. Do not mirror props unless you mean "draft." Copying props into $state creates two sources of truth — derive from props, or make a named editable draft with reset/commit. See references/prop-mirroring.md.
<!-- ❌ prop mirrored into local state -->
let { value } = $props();
let local = $state(value); // stale if parent changes
<!-- ✅ derive from prop -->
let { value } = $props();
let display = $derived(value.toUpperCase());8. Context shares identity, not provider rerenders. Put a reactive object/class in context and mutate its properties; replacing plain values won't behave like React Provider updates. See references/context-identity.md.
9. Module-level mutable state is suspicious in SSR apps. In SvelteKit, exported mutable instances leak between requests — use factories, context, or request-owned data. See references/ssr-state-leaks.md.
Design component APIs around ownership
10. Props describe inputs; callbacks describe events. Component events are callback props; avoid createEventDispatcher in new code unless preserving an old public API. See references/component-patterns.md.
<!-- ❌ createEventDispatcher in Svelte 5 -->
const dispatch = createEventDispatcher();
function handleClick() { dispatch('select', item); }
<!-- ✅ callback prop -->
let { onSelect } = $props();
function handleClick() { onSelect?.(item); }11. Two-way binding is an API commitment. $bindable means the child may mutate parent-owned state — use it for form controls and deliberate controlled components, not as a default. See references/bindable-by-default.md.
12. Snippets are render functions, not renamed slots. Use them when the parent supplies UI; type their parameters and name them by role. See references/snippets-as-render-functions.md.
13. Wrapper components should preserve the platform. Wrapping a button means accepting button attributes and keeping type, disabled, focus, and ARIA intact. See references/wrapper-components-preserve-html.md.
Let HTML and the compiler work
14. Native elements before custom behavior. A button already handles keyboard, focus, disabled, and a11y; a clickable div rebuilds the platform badly. See references/semantic-html-first.md.
15. Design-system fields should preserve form semantics. In shadcn-svelte or bits-ui forms, use Field.* for labels, groups, descriptions, and errors — not raw divs, separate Label imports, or clickable option rows. See references/shadcn-svelte-forms.md.
16. Components own markup; actions/attachments own DOM behavior. Renders UI → component. Attaches reusable imperative behavior to an element → action or attachment. See references/actions-vs-components.md.
17. Svelte 5 syntax should be consistent. New code uses $props, onclick-style attributes, snippets, and callback props; don't mix old syntax outside legacy maintenance. See references/svelte5-syntax-discipline.md.
18. Type the boundary, not every breath. Non-trivial components get a Props type; type snippets and callbacks; use svelte/elements for wrappers; avoid broad any at boundaries. See references/typescript.md.
Running a Review
- Detect the version first. Read
package.jsonfor thesveltemajor and checksvelte.config.*. In a Svelte 5 project, flag Svelte 4 patterns (export let,on:event,<slot>,createEventDispatcher); in a Svelte 4 project, do not recommend Svelte 5-only syntax unless the task is migration. - Apply the principles above; scan the smell index below. Open the linked reference before proposing a rewrite.
- Judge performance only on evidence or obvious scale. Key identified
{#each}, move heavy work out of markup into$derived, avoid needless two-way bindings. Most code needs no manual optimization. - Shape the output: high-impact first (correctness, reactivity, a11y, SSR leaks), then suggested rewrites (smallest useful change), then nice-to-haves. Tie every point to behavior, maintainability, or user impact — not every stylistic nit.
Code Smell Index
Scan for the smell; the principle above carries the fix.
| Code smell | Reference |
|---|---|
| Old Svelte syntax in new code | svelte5-syntax-discipline |
| Effect assigns a derived value | effect-driven-state |
| Effect responds to a control changing | effect-driven-state |
| Effect converts a bound value | bindings-and-directives |
| Effect reruns mysteriously | read-tracked-reactivity |
| Rune called inside a helper or hook | static-runes |
| Immutable-update ceremony on local state | deep-state-without-immutable-ceremony |
| Prop copied into local state | prop-mirroring |
| Global store by default / owner unclear | state-ownership |
| Context value replaced instead of mutated | context-identity |
| Exported mutable singleton in SvelteKit | ssr-state-leaks |
createEventDispatcher to emit an event | component-patterns |
$bindable by habit | bindable-by-default |
Slot-shaped API (export let, <slot>) | snippets-as-render-functions |
Clickable div / span | semantic-html-first |
| shadcn-svelte form rebuilt with raw wrappers | shadcn-svelte-forms |
| Wrapper that hides native behavior | wrapper-components-preserve-html |
| Action that owns markup/state | actions-vs-components |
| Dynamic list left unkeyed | bindings-and-directives |
Broad any at the component boundary | typescript |
{@html} with user content | template-tags |
| Component behavior left untested | testing |
Cross-References
- sveltekit — Routes, layouts,
load, form actions, remote functions, cookies, auth, endpoints, redirects, server errors, app-level SSR/data flow


