web-framework-svelte-aadf3c — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited web-framework-svelte-aadf3c (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Quick Guide: Runes make reactivity explicit and portable out of.sveltefiles.$statefor values that change,$derivedfor everything computed from them,$effectonly for reaching outside the component. Snippets replace slots, callback props replacecreateEventDispatcher, andonclickreplaceson:click. The Svelte 4 forms still compile, so nothing flags them.
Detailed Resources:
$state, $state.raw, $derived, $props, $bindable, $effect, $effect.pre$inspect, context, shared state modules, class-based state, $state.snapshot, $state.eager$props(), and teardown belongs in the function an $effect returns.$state and $derived work, but a reassigned export does not propagate to importers, because the binding is copied at import. Export an object or a class holding $state fields instead: examples/advanced.md.<critical_requirements>
Declare changing values with `$state` and compute from them with `$derived`. A $derived recomputes lazily and cannot fall out of step; the same value maintained by an $effect updates after the DOM has already painted the old one.
Pass composable markup as snippets — `{#snippet}` declares it, `{@render}` renders it. Snippets are typed, take parameters, and can be passed as props; <slot> did none of that.
Let a child notify its parent through a callback prop — `onsave`, `onselect`. The signature is checked at the call site, where a dispatched event's payload was not.
Reach for `$state.raw()` when a value is replaced wholesale rather than mutated. It skips the deep proxy, which is the whole cost on a large array that only ever gets reassigned.
Reach for `createContext<T>()` over `setContext`/`getContext`. It hands back a typed [get, set] pair with the key minted for you, so no consumer casts and no two libraries collide on a string key — examples/advanced.md has it.
</critical_requirements>
Auto-detection: Svelte 5, runes, $state, $derived, $effect, $props, $bindable, $inspect, .svelte, .svelte.ts, {#snippet}, {@render}, Snippet, createContext, setContext, getContext, $state.raw, $state.snapshot, $state.eager, $derived.by, $effect.pre, ClassValue
Applies to:
$bindableHandled elsewhere:
<style> block is scoped by the compiler, and which CSS approach fills it is not settled here<philosophy>
Svelte 4 inferred reactivity from position: a let at the top level of a component was reactive, $: re-ran on assignment, and neither meant anything in a .ts file. Runes replace that with a marker on the value itself, so the same declaration behaves identically in a component, a module and a class field.
The ordering that follows is: $derived for anything computable, an event handler for anything a user triggers, and $effect only for what is genuinely outside the component — a canvas, a third-party widget, a subscription. An $effect that assigns to $state is a $derived written the long way round, and it runs after the DOM update rather than before it.
</philosophy>
<patterns>
$state makes a value reactive and, for objects and arrays, deeply so — push and property assignment are both tracked, with no immutable update dance.
<script lang="ts">
let count = $state(0);
let todos = $state<Todo[]>([]);
function addTodo(text: string) {
todos.push({ done: false, text });
}
</script>Full code: examples/core.md
$derived takes an expression, $derived.by a function for anything longer. Both recompute only when a dependency actually changed.
<script lang="ts">
let doubled = $derived(count * 2);
let stats = $derived.by(() => ({
isEven: count % 2 === 0,
isPositive: count > 0,
}));
</script>Full code: examples/core.md
Props are destructured out of $props() with defaults and rest, and typed by an interface.
<script lang="ts">
interface Props {
name: string;
role?: string;
class?: string;
}
let { name, role = 'member', ...rest }: Props = $props();
let initials = $derived(name.split(' ').map((n) => n[0]).join(''));
</script>Destructuring $props() is the one place it is safe — the compiler keeps the bindings live. Destructuring a $state object does not.
Full code: examples/core.md
$bindable marks a prop the child may write back through bind:. Worth it for form primitives; for everything else a callback prop keeps the data flowing one way.
<!-- text-input.svelte -->
<script lang="ts">
let { value = $bindable(''), placeholder = '' }: Props = $props();
</script>
<input bind:value {placeholder} />
<!-- parent.svelte -->
<TextInput bind:value={searchQuery} placeholder="Search..." />Full code: examples/core.md
An effect reaches outside the component; the function it returns is the teardown, run before the next execution and on unmount.
<script lang="ts">
$effect(() => {
const timer = setTimeout(() => search(query), DEBOUNCE_MS);
return () => clearTimeout(timer);
});
</script>Anything of the form $effect(() => { x = f(y) }) is a $derived. Anything triggered by a click is an event handler. Anything you wanted to log is $inspect.
Full code: examples/core.md
{#snippet} declares a block of markup and {@render} renders it. Content between a component's tags becomes its children snippet automatically; anything else is a prop typed Snippet.
<script lang="ts">
import type { Snippet } from 'svelte';
let { title, children, footer }: { title: string; children: Snippet; footer?: Snippet } = $props();
</script>
<h2>{title}</h2>
{@render children()}
{#if footer}{@render footer()}{/if}Full code: examples/snippets.md
Element events are plain attributes. Component events are callback props, optional ones called with ?.().
<script lang="ts">
let { color, onchange, onreset }: Props = $props();
</script>
<button onclick={() => onchange?.('red')}>Red</button>
{#if onreset}<button onclick={onreset}>Reset</button>{/if}Full code: examples/events.md
</patterns>
<red_flags>
Breaks at runtime:
$state object — the values are read once at destructure time and never again$state.raw value — only reassignment is tracked, which is the trade it exists to makesetContext called from an event handler or an $effect — context is only settable during component initialisation$effect created outside component or module initialisation — calling it from an event handler is a runtime error rather than a silent no-op; $effect.root() is how an effect scope gets opened by hand, and it hands back its own cleanupawait inside an $effect — those reads are not tracked, so the effect never re-runs for them$derived — only $effect runs one$effect relied on during server rendering — it runs in the browser onlySurprising behaviour:
export let, $:, <slot>, createEventDispatcher, on:click, <svelte:component this={X}>. Nothing warns, so a file can be half-migrated and look fine$state value is a proxy, not the object you passed — $state.snapshot() before serialising or handing it to a library that compares identity$derived result is not deeply reactive; only $state creates the proxy$props() are not proxied either$effect runs after the DOM update — $effect.pre is the hook for measuring before it$inspect compiles to nothing in production, so it is a debugging tool rather than loggingstopPropagation() reaches</red_flags>
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.