From frontend
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.
npx claudepluginhub xobotyi/cc-foundry --plugin frontendThis skill uses the workspace's default tool permissions.
**Reactivity is explicit, compiler-driven, and minimal-runtime.** Every reactive declaration uses a `$` rune. The
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Reactivity is explicit, compiler-driven, and minimal-runtime. Every reactive declaration uses a $ rune. The
compiler transforms declarative code into surgical DOM updates -- no virtual DOM, no diffing, no hidden magic.
References contain extended examples, rationale, and edge cases for each topic.
${CLAUDE_SKILL_DIR}/references/runes.md]: $state, $derived, $effect, $props, $bindable
details${CLAUDE_SKILL_DIR}/references/components.md]: Snippets, events, context, special elements${CLAUDE_SKILL_DIR}/references/sveltekit.md]: Routing, load functions, form actions, hooks, imports$state$state or $state.raw. Plain let declarations are not reactive.$state objects breaks reactivity -- destructured values are snapshots, not live references.$state on class fields or as first assignment in constructor. The compiler transforms these into getter/setter
pairs. Use arrow functions to preserve this in event handlers on classes.$state.raw opts out of deep reactivity -- state can only be reassigned, not mutated. Use for large arrays/objects
you replace wholesale to avoid proxy overhead.$state.snapshot(value) takes a static copy of a reactive proxy for external APIs that don't expect proxies (e.g.,
structuredClone, logging).Set, Map, Date, URL from svelte/reactivity when you need reactive built-in types.Cannot directly export reassignable $state. Two patterns:
$state({ count: 0 }) as a const, mutate properties, export modifier
functions.$state private, export getCount() and increment().Runes only work in .svelte and .svelte.js/.svelte.ts files.
$derived$derived for all computed values -- never synchronize state with $effect.$derived.by(() => { ... }) for complex derivations needing a function body.untrack to exempt specific reads.$derived values are individually reactive.$effect$effect is an escape hatch. Use only for side effects: DOM manipulation, analytics, third-party library calls,
timers.await or inside setTimeout are NOT tracked.$effect.pre runs before DOM updates -- use for pre-DOM manipulation like autoscrolling.$effect.tracking() returns true if code is running inside a tracking context.$effect.root(() => { ... }) creates a non-tracked scope for manual effect lifecycle control. Returns a destroy
function.Never use $effect to synchronize state -- use $derived with callback event handlers or function bindings
instead.
$propslet { name, count = 0 } = $props().let { name }: Props = $props().let { class: klass } = $props().let { a, b, ...rest } = $props().let props = $props().$props.id() -- consistent across SSR/hydration.$bindable. Use callback props to
communicate changes upward.$bindablelet { value = $bindable() } = $props().bind:value={variable}.$inspect$inspect(count, message) logs when tracked values change.$inspect(value).with((type, ...args) => { ... }) replaces default console.log with custom callback. Type is
"init" or "update".$inspect.trace() traces which reactive state caused a re-execution. Must be first statement in a function body.$hostOnly available inside custom elements. Provides access to the host element for dispatching custom events.
$props())$state)$derived)$effect, sparingly)<style>)<MyComponent />. Required for dynamic rendering.item.component).<svelte:component> is unnecessary. Just use <Thing /> where Thing is a
reactive variable.onclick={handler}, never on:click={handler}.onclick listens to click, onClick listens to Click.event.preventDefault() / event.stopPropagation() in the handler. For capture, append to
event name: onclickcapture={...}.let { onEvent } = $props(). Never use
createEventDispatcher.click, input, keydown) -- single listener at app root. When
manually dispatching events, set { bubbles: true }. Prefer on from svelte/events over raw addEventListener.{@render children?.()} for default content. Never use <slot />.{#snippet header()}...{/snippet} in parent, accept as props, render with
{@render header()}.{@render item(entry)} in child, {#snippet item(text)} in
parent.{@render children?.()} or {#if children} with fallback.<script module> for cross-component use.Snippet and Snippet<[ParamType]> from svelte.Control flow:
{#if} / {:else if} / {:else} / {/if} for conditional blocks.{#each items as item, index (item.id)} with key expression for lists. Always provide a key for lists that can
change. :else renders when array is empty.{#key value} destroys and recreates contents when value changes -- triggers entry transitions or resets component
state.{#await promise} / {:then value} / {:catch error} for async. Short forms: {#await promise then value} skips
loading state.Special tags:
{@html rawHtml} -- render raw HTML (escape user input to prevent XSS).{@const x = expr} -- declare local constant inside a block scope.{@debug var1, var2} -- trigger debugger when values change.{@render snippet()} -- render a snippet.{@attach action} -- attach an action to an element.Text expressions: {expression} outputs stringified, escaped value. null and undefined are omitted.
Conditional classes: object syntax like clsx: class={{ cool, lame: !cool }}.
setContext(key, value) / getContext(key) passes data through the component tree without prop drilling.createContext<T>() from svelte which returns [getContext, setContext] pair.setContext to maintain reactivity across boundaries.<svelte:boundary> -- error boundary. Use {#snippet failed(error, reset)} for error UI and {#snippet pending()}
for loading state with await expressions.<svelte:window> -- bind to window events and properties (bind:scrollY).<svelte:head> -- insert elements into document.head (SEO meta tags, title).<svelte:element this={tag}> -- render a dynamic HTML element.<svelte:options> -- set compiler options (customElement, namespace).Components are functions, not classes:
mount(Component, { target }) for client-side mounting.unmount(app) to destroy.hydrate instead of mount for server-rendered HTML.$state is shared across requests during SSR. Use context or
event.locals instead.load, don't write to globals. No side effects in load functions.setContext/getContext for data that must not leak between requests.$derived for reactive computed values in components -- plain assignments in <script> run once, not reactively..svelte.js / .svelte.ts for reactive modules -- runes only work in .svelte and .svelte.js/.svelte.ts files.$lib for shared code -- import from $lib/ instead of relative paths climbing multiple levels.+page.svelte — Page component (receives data from load)+page.js — Universal load (server + browser)+page.server.js — Server-only load + form actions+layout.svelte — Layout wrapper (must render {@render children()})+layout.js — Layout universal load+layout.server.js — Layout server load+error.svelte — Error boundary+server.js — API endpoint (GET, POST, etc.)Key rules: all files can run on the server. All run on the client except +server files. +layout and +error apply
to subdirectories too.
Decision tree:
| Need | Use |
|---|---|
| Database, private keys | +page.server.js (PageServerLoad) |
| Non-serializable return values | +page.js (PageLoad) |
| External API, no secrets | +page.js (PageLoad) |
| Both | Both (server data flows to universal) |
Universal vs server:
| Aspect | Universal (+page.js) | Server (+page.server.js) |
|---|---|---|
| Runs on | Server (SSR) + Browser | Server only |
| Access | params, url, fetch | + cookies, locals, request |
| Returns | Any value (classes, components) | Serializable data only |
fetch, not global fetch -- inherits cookies, makes relative requests work on server, bypasses
HTTP overhead for internal requests.+page.js: prerender, ssr, csr.params change, url properties change, parent() was
called and parent reran, or invalidate()/invalidateAll() called.error() and redirect() from @sveltejs/kit for error and redirect responses.Server-only POST handlers in +page.server.js. Work without JavaScript.
export const actions = { default: async ({ request }) => { ... } }.action="?/login" on form, multiple actions in the actions object.fail(400, { field, missing: true }) from action. Access via form prop in the page component.use:enhance from $app/forms for JS-enhanced submission without full page reload.Export HTTP verb handlers from +server.js: GET, POST, PUT, PATCH, DELETE. Return json() or
new Response().
Server hooks (src/hooks.server.js):
handle({ event, resolve }) -- intercept every request. Set event.locals, modify response headers.handleFetch -- modify server-side fetch calls.handleError -- log and sanitize unexpected errors.init -- run once at server startup.Client hooks (src/hooks.client.js):
handleError -- client-side error handling.Universal hooks (src/hooks.js):
reroute -- rewrite URLs before routing.transport -- serialize/deserialize custom types across server/client boundary.Most-used modules: $app/navigation (goto, invalidate), $app/state (page, navigating), $app/forms
(enhance), $env/static/private and $env/static/public for environment variables, $lib for shared code. Full
imports table in ${CLAUDE_SKILL_DIR}/references/sveltekit.md.
load functions to avoid browser-to-API waterfalls.$derived instead of $effect for computed values.<body>).@sveltejs/enhanced-img for image optimization.import() for conditional code.When writing Svelte code:
When reviewing Svelte code:
This skill provides Svelte-specific conventions. The coding skill governs workflow; for TypeScript projects, the typescript skill handles language-level choices; for CSS concerns, the css skill handles styling conventions.