SvelteKit has its own mental model for routing, data loading, and reactivity. It's not React. It's not Next.js. AI tools that treat it like React produce code that compiles but fights the framework at every turn.
The failure modes are predictable: useEffect where a load function belongs, fetch in components where form actions should handle mutations, React hook patterns in Svelte component logic, useState where Svelte's reactive declarations work better.
A CLAUDE.md file at the repo root fixes this by declaring the SvelteKit model upfront. Here are 13 rules that cover the most common drift patterns.
Rule 1: This is SvelteKit, not React
This project uses SvelteKit with Svelte 5.
Do NOT generate React patterns:
- No useState, useEffect, useRef, useContext
- No JSX syntax
- No React component lifecycle methods
- No react-router or react-query
Use Svelte's reactivity model and SvelteKit's conventions.
Rule 2: Load functions own server-side data fetching
Data fetching for routes lives in +page.server.ts (server) or
+page.ts (universal) load functions.
Do NOT fetch data in onMount or component-level code
when a load function can handle it.
Access load data via the data prop: export let data.
Rule 3: Form actions own all mutations
Form submissions and data mutations use SvelteKit form actions
defined in +page.server.ts.
Use the enhance action for progressive enhancement.
Do NOT use fetch() in components for mutations that a form
action can handle.
Rule 4: File-system routing conventions
+page.svelte: the page UI
+page.server.ts: server-only load + actions
+page.ts: universal load (runs on server + client)
+layout.svelte: shared UI for a route segment
+layout.server.ts: shared server data for a segment
+error.svelte: error page for a segment
+server.ts: API endpoint (GET, POST, etc.)
Do not put server logic in +page.svelte or +page.ts.
Rule 5: Svelte 5 reactivity uses runes
This project uses Svelte 5 runes syntax:
$state() for reactive state
$derived() for computed values
$effect() for side effects (use sparingly)
$props() for component props
Do NOT use Svelte 4 reactive declarations ($:) unless
the project explicitly uses Svelte 4 compatibility mode.
Rule 6: Stores for cross-component state
Shared state uses Svelte stores (writable, readable, derived)
imported from svelte/store.
Do NOT use React Context, Redux, or Zustand.
For server-side shared state: use locals in handle hooks.
Rule 7: Transitions and animations use Svelte built-ins
Animations: svelte/transition, svelte/animate, svelte/motion
Do NOT use Framer Motion, React Spring, or CSS-in-JS libraries.
Use Svelte's directive syntax: transition:fade, in:fly, etc.
Rule 8: Environment variables use $env modules
Private server vars: import from '$env/static/private'
Public vars: import from '$env/static/public'
Dynamic vars: '$env/dynamic/private' or '$env/dynamic/public'
Do NOT use process.env directly in SvelteKit code.
Do NOT expose private env vars in +page.ts or +page.svelte.
Rule 9: Path aliases use $lib
Shared code lives in src/lib/ and is imported via '$lib/...'
Do NOT use relative imports like '../../../lib/...'
Components: '$lib/components/Button.svelte'
Utilities: '$lib/utils/format.ts'
Rule 10: API endpoints use +server.ts files
HTTP endpoints: src/routes/api/[path]/+server.ts
Export named functions: GET, POST, PUT, DELETE, PATCH
Return Response objects or use json() helper from @sveltejs/kit
Do NOT create a separate Express server for API routes.
Rule 11: Error handling uses SvelteKit conventions
Expected errors: error() from '@sveltejs/kit' in load/actions
Unexpected errors: handled by +error.svelte
Do NOT use try/catch to swallow errors in load functions —
throw the error() helper and let SvelteKit handle routing.
Rule 12: SSR and hydration are opt-in/opt-out
SSR is enabled by default. To configure:
export const ssr = false; // disable SSR for a route
export const prerender = true; // static generation
export const csr = false; // disable client-side rendering
Do NOT replicate SSR/hydration logic manually.
Rule 13: Component props use $props() in Svelte 5
Define props at the top of the script block:
let { title, count = 0, onchange }: { title: "string; count?: number; onchange?: () => void } = $props();"
Do NOT use export let for Svelte 5 components.
Do NOT use React prop patterns (defaultProps, PropTypes).
The full CLAUDE.md block
# SvelteKit Project Rules (Svelte 5)
## Framework
- SvelteKit + Svelte 5 — NOT React or Next.js
- No React hooks, JSX, or React lifecycle patterns
## Routing (file-system)
- +page.svelte: UI
- +page.server.ts: server load + actions
- +page.ts: universal load
- +layout.svelte/.server.ts: shared segments
- +server.ts: API endpoints
- +error.svelte: error pages
## Data & Mutations
- Server data: load functions in +page.server.ts
- Mutations: form actions in +page.server.ts
- No fetch() in components for server mutations
## Svelte 5 Reactivity
- $state(), $derived(), $effect(), $props()
- No Svelte 4 $: reactive declarations
## State
- Cross-component: Svelte stores (svelte/store)
- No React Context, Redux, Zustand
## Environment
- Private: $env/static/private
- Public: $env/static/public
- No process.env in SvelteKit modules
## Paths
- $lib/... for shared code (not relative imports)
## SSR
- SSR on by default
- export const ssr/prerender/csr to configure
Why SvelteKit AI drift is common
The web is full of React tutorials. SvelteKit has a much smaller training footprint. When AI generates "a web framework component with data fetching," it defaults to React patterns because that's what it has seen most.
SvelteKit's conventions are fundamentally different from React in three ways: the reactivity model (compiler-based vs. hook-based), the data layer (file-system load functions vs. useQuery), and the mutation pattern (form actions vs. onClick + fetch).
The CLAUDE.md file tells the AI which paradigm you're working in. Without it, it guesses — and it guesses React.
These 13 rules are part of a framework-specific CLAUDE.md series. The Cursor Rules Pack equivalent (50 production-tested rules across all stacks) is available at oliviacraftlat.gumroad.com/l/wyaeil — search "Olivia Craft Cursor Rules" on Gumroad.
Top comments (0)