# Svelte 5 Patterns and Rules This document contains Svelte-specific implementation rules. Only read this file when modifying Svelte components, routes, or Svelte-specific logic. --- # Svelte Version This project uses: - SvelteKit 2 - Svelte 5 - runes mode Always use: - $state() - $derived() - $effect() - $props() Do not use legacy stores: - writable() - readable() - derived() --- # Component Props Always destructure $props() with defaults. Preferred pattern: let { record = {} as Record, fieldErrors = {} as Record, isSuper = false }: { record?: Record; fieldErrors?: Record; isSuper?: boolean; } = $props(); Do not assume props exist. --- # State Synchronization IMPORTANT: Do not initialize $state from props when the prop can change. Incorrect: let name = $state(record.name); This only captures the initial value. Correct: let name = $state(''); $effect(() => { name = String(record.name ?? ''); }); Use $effect whenever component state needs to follow changing props. --- # Effect Ordering $effect blocks execute in declaration order. When multiple effects modify related state: 1. Reset state first. 2. Populate state second. 3. Perform dependent calculations afterward. Example: let dirty = $state(false); $effect(() => { dirty = false; }); $effect(() => { name = String(record.name ?? ''); }); This ensures a new record starts clean. --- # Select Inputs IMPORTANT: Do not use bind:value on select elements whose values are synchronized through $effect. Incorrect: This can fail to update correctly. Use: Use selected on options. --- # Input Elements Text inputs are different. This is acceptable: bind:value works correctly with normal input elements. --- # Forms Admin forms use: - $state for field values - $effect for prop synchronization - oninput for dirty tracking - use:enhance for submission Example:
--- # Avoid Unnecessary State Prefer: $derived() for values computed from other state. Use: $state() only for values that change independently. --- # Component Changes Before modifying a component: 1. Read the entire component. 2. Find similar components. 3. Follow existing patterns. 4. Avoid introducing new abstractions unless necessary. Small, consistent changes are preferred.