20 lines | 1.8 KB

AGENTS.md — SvelteKit (Svelte 5)

  • Use Svelte 5 runes; treat export let and $: reactive statements as legacy — don't write them.
  • Declare reactive state with $state(...); arrays/objects become deep reactive proxies you can mutate.
  • Use $state.raw(...) to opt out of deep reactivity (reassign only, never mutate).
  • Compute values with $derived(expr) or $derived.by(fn); keep the expression side-effect-free.
  • Read props with $props(); support defaults/rename/rest via destructuring. Props are read-only — don't mutate them.
  • For two-way binding use $bindable(); otherwise communicate changes via callback props.
  • $effect(...) is for side-effects (analytics, DOM, external sync), not for deriving state — use $derived for that.
  • Don't read and write the same state inside one $effect (infinite loop); use untrack(...) if needed.
  • Routes are filesystem-based under src/routes: [slug] dynamic, [...rest] rest, [[opt]] optional params.
  • +page.svelte gets data via the data prop; +layout.svelte renders children with {@render children()}.
  • +server.js exports GET/POST/etc. handlers returning a Response.
  • Use +page.server.js / +layout.server.js (server load) for DB, secrets, cookies, locals; return devalue-serializable data.
  • Use +page.js / +layout.js (universal load) for public fetches and non-serializable return values.
  • Use the injected fetch in load; read params/url, await parent(), throw redirect() / error().
  • Never store per-user state in server module-level variables — it leaks across requests. Use setContext/getContext.
  • Keep load pure (no side-effects); persist navigation state in URL search params, ephemeral UI state in snapshots.
  • Types come from ./$types (PageData, PageLoad, PageServerLoad, RequestHandler).