joshuadavidthomas/agent-skills

svelte5

Reviews Svelte components for idiomatic patterns, identifies anti-patterns carried over from React/Vue/Svelte 4, and suggests Svelte 5 refactorings.

View source

How to use

  1. Copy the installation command and review the source package before installing it in your own agent environment.
  2. Check the source document for required tools, credentials and supported hosts.
  3. Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/joshuadavidthomas/agent-skills --skill svelte5

Before 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.
Original skill document

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.

svelte
<!-- ❌ 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.

svelte
<!-- ❌ 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.

svelte
<!-- ❌ 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

  1. Detect the version first. Read package.json for the svelte major and check svelte.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.
  2. Apply the principles above; scan the smell index below. Open the linked reference before proposing a rewrite.
  3. 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.
  4. 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 smellReference
Old Svelte syntax in new codesvelte5-syntax-discipline
Effect assigns a derived valueeffect-driven-state
Effect responds to a control changingeffect-driven-state
Effect converts a bound valuebindings-and-directives
Effect reruns mysteriouslyread-tracked-reactivity
Rune called inside a helper or hookstatic-runes
Immutable-update ceremony on local statedeep-state-without-immutable-ceremony
Prop copied into local stateprop-mirroring
Global store by default / owner unclearstate-ownership
Context value replaced instead of mutatedcontext-identity
Exported mutable singleton in SvelteKitssr-state-leaks
createEventDispatcher to emit an eventcomponent-patterns
$bindable by habitbindable-by-default
Slot-shaped API (export let, <slot>)snippets-as-render-functions
Clickable div / spansemantic-html-first
shadcn-svelte form rebuilt with raw wrappersshadcn-svelte-forms
Wrapper that hides native behaviorwrapper-components-preserve-html
Action that owns markup/stateactions-vs-components
Dynamic list left unkeyedbindings-and-directives
Broad any at the component boundarytypescript
{@html} with user contenttemplate-tags
Component behavior left untestedtesting

Cross-References

  • sveltekit — Routes, layouts, load, form actions, remote functions, cookies, auth, endpoints, redirects, server errors, app-level SSR/data flow

Related by task

from this repository

More skills

All skills
joshuadavidthomas
Community

english-please

Dude, come on. You write at the density of your own thinking and leave the reader to unpack it. Apply whenever explaining anything to a human — not just end-of-run summaries, every message.

installs
1
GitHub stars
56
Updated
Jul 20
joshuadavidthomas
Community

frontend-design-principles

Use when building or reviewing frontend UI — dashboards, admin panels, landing pages, marketing sites, web apps. Drives domain-specific design decisions (typography, color world, layout, CSS token naming, depth and spacing systems) instead of generic AI defaults; routes to app.md (product/data UIs) or marketing.md (public/creative pages) by context.

installs
1
GitHub stars
56
Updated
Jul 20
joshuadavidthomas
Community

grug-brained-dev

Use when reviewing PRs, simplifying over-engineered code, judging architecture, or renaming unclear concepts — inline fake helpers, delete meatless ceremony, rename lying names, merge over-split files, reject premature abstraction, say no to speculative config/modes/layers, then end with the smallest safe next change. Triggers when code is too fancy, too abstract, too clever, too many files/helpers/layers, or too well-factored but painful to change. Embody Grug brain: complexity very bad, small

installs
1
GitHub stars
56
Updated
Jul 20
joshuadavidthomas
Community

improve

Survey a codebase as a senior advisor and turn the highest-value findings into implementation plans for other agents to execute — strictly read-only on source code, never implements anything itself. Use when asked to audit a codebase, find improvement opportunities (bugs, security, performance, test coverage, tech debt, architecture, migrations, DX), suggest features or roadmap direction, or generate handoff plans for another agent to implement.

installs
1
GitHub stars
56
Updated
Jul 20