Review checklist
This is the checklist to run down — by eye, on any diff, yours or an AI’s — after the tools in Verification Tools have run and come back clean. It fits on one printed page on purpose: a checklist nobody actually opens during a review is worthless. Every line links to the lesson that explains why, so this page stays a list, not a re-run of the course. The groups follow the same order as How to read Svelte you did not write.
flowchart LR R["Runes vs legacy mode"] --> C["Compiler catches SOME<br/>(export let/$: hard errors; slot/on:click only warn)"] S["State ownership"] --> H["Mostly human review<br/>(a running test is the only real check)"] P["Props/bindings/snippets"] --> C E["Events and DOM"] --> H B["SvelteKit boundary"] --> H K["Keys, transitions, boundaries"] --> H
Runes vs legacy mode
Section titled “Runes vs legacy mode”- Does the file mix any rune (
$state,$derived,$effect,$props) withexport letor a top-level reactive$:? Both are hard compile errors the instant a rune is present. See the AI Bug Catalog, entry 2. - Is
<slot>used anywhere in a file that otherwise uses runes? It still compiles (a real deprecation warning, not an error) — should be achildren/named snippet instead. See entry 3. - Is
on:click-style directive syntax used instead of the plainonclickproperty? See entry 1. - Is
createEventDispatcherused in new code where a plain, typed callback prop would be simpler and equally idiomatic? See entry 4. - Does
eslint-plugin-svelte’s config actually enablesvelte/valid-compile— the rule that surfaces the compiler’s own deprecation/error diagnostics as lint output — or does the project rely onrecommendedalone, which does not include it? See Verification Tools.
State ownership
Section titled “State ownership”- Could this
$effectthat assigns to a$statevariable just be$derivedinstead? See the AI Bug Catalog, entries 5 and 6. - Is a value read inside a
setTimeout/Promise/callback that runs after the surrounding$effect/$derivedalready finished its synchronous pass, with an expectation that it’s still a tracked dependency? See entry 7. - Is a
$state.rawvalue ever mutated in place (.prop = x,.push(...)) with an expectation that the UI updates, instead of being reassigned? See entry 8. - Does a
$derivedbody do anything besides compute and return a value — an API call,console.log, pushing to an outside array? See entry 9. - Is a value computed once inside
onMountwhen it should recompute whenever a prop/state it depends on changes? See entry 10. - Is a
.svelte.ts/.svelte.jsmodule’s exported$state(bare, or a directly-exported class instance) ever mutated inside aloadfunction or request handler — data that should be created fresh per request instead? See entry 11. - Is
$store(the$-prefixed shorthand) ever read anywhere other than a component’s or module’s top level? See entry 12. - Is
get(store)called repeatedly inside a loop, a frequently-run$effect, or on every keystroke, instead of subscribing once? See entry 13. - Is a store (
writable/readable/derived) ever wrapped a second time in$state, mixing two reactivity systems that track nothing useful together? See entry 14.
Props, bindings, and snippets
Section titled “Props, bindings, and snippets”- Does a parent do
<Child bind:value={x} />whenChildnever declaredvalue = $bindable()? See the AI Bug Catalog, entry 15. - Is every
{#snippet name(...)}in the file actually rendered somewhere with a matching{@render name(...)}— never left orphaned, never called as a bare{name(...)}? See entries 16 and 17. - Does a
bind:valueon atype="number"/type="range"input get treated as a string anywhere downstream (.trim(),.length, string concatenation). See entry 18. - Is a snippet prop typed with
Snippet<[T]>when it takes a parameter, so a mismatched shape is a compile-timesvelte-checkerror rather than a runtime surprise? See Passing UI & Children.
Events and the DOM
Section titled “Events and the DOM”- Does a
use:action={value}site assumevalueupdates the DOM automatically, with noupdatemethod defined on the action — or could it be a Svelte 5.29+ attachment instead? See the AI Bug Catalog, entry 19. - Does any manually-attached
addEventListenerbetween the DOM root and a SvelteonclickcallstopPropagation(), silently defeating the delegated handler? See entry 20. - Does code needing
passive/oncesemantics use theonfunction fromsvelte/events, rather than a plain attribute that cannot express those options? - Is
use:ever attempted on a component (<MyComponent use:foo />)? It only works on DOM elements — an attachment is the component-compatible equivalent.
The SvelteKit boundary
Section titled “The SvelteKit boundary”- Does a
try/catchwrap a call toredirect()/error()without checkingisRedirect/isHttpErrorbefore treating the catch as a real failure? See the AI Bug Catalog, entry 22. - Does
+page.js(a universal load) import$env/static/private,$env/dynamic/private, or any other server-only module? See entry 24. - Does a form action return a plain object on validation failure instead of
fail(status, data)? See entry 25. - Does a
loadfunctionawaita value the first paint doesn’t need, instead of returning the promise unawaited for{#await}to stream? See entry 23. - Does the code import
page/navigating/updatedfrom$app/storesinstead of the non-deprecated$app/state? See entry 21. - Is
event.localsused anywhere without a matchingApp.Localsinterface declared insrc/app.d.ts?
Keys, transitions, and boundaries
Section titled “Keys, transitions, and boundaries”- Does every
{#each}over a list of components (or elements with meaningful local state) use a stable, data-derived key — never the array index, never omitted entirely? See the AI Bug Catalog, entry 26. - Is
reset()ever called synchronously inside a<svelte:boundary onerror>callback, instead of from a separate action or behindawait tick()? See entry 28. - Does
awaitappear directly in a template or$derivedwithoutcompilerOptions.experimental.async: trueset anywhere in the project? See entry 27. - Does code assume a
<svelte:boundary pending>snippet will show for every async update, including ones after the first render — when only$effect.pending()covers that case? - Is there a
<svelte:boundary>around a subtree that can genuinely throw during render or in an effect, with a realfailed/onerror— or does one broken widget risk unmounting the whole page?