-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsvelte-kit.mdc
More file actions
133 lines (103 loc) · 7.43 KB
/
Copy pathsvelte-kit.mdc
File metadata and controls
133 lines (103 loc) · 7.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
---
description: SvelteKit load functions, form actions, and typed routing — no onMount data fetching.
globs: ""
alwaysApply: true
---
## File Structure and Naming
- All routes must be in `src/routes/` with `+page.svelte`, `+page.ts`, `+layout.svelte`, `+layout.ts` naming only
- Server-only code lives in `+page.server.ts` or `+layout.server.ts` — never in `+page.ts`
- Reusable components go in `src/lib/components/` with PascalCase filenames matching export name exactly
- Utility functions go in `src/lib/utils/` with camelCase filenames, one function per file unless logically grouped
- Stores go in `src/lib/stores/` with camelCase filenames, one store per file
- Types go in `src/lib/types/` with camelCase filenames, one type definition per file
- Never create files outside `src/` except config files in project root
## TypeScript Enforcement
- Every `.ts` file must have explicit return types on all functions — no implicit `any` returns
- Every `+page.ts` and `+layout.ts` must export typed `load` function with explicit `PageLoad` or `LayoutLoad` return type
- Never use `as` type assertions — use type guards with `if (x instanceof Type)` or Zod `.parse()`
- All function parameters must have explicit types — no `(x) =>` syntax allowed
- All object literals must have explicit type annotations or be assigned to typed variables
- Never use `any` type — use `unknown` and narrow with type guards instead
## Data Loading and Server Communication
- All data fetching must happen in `+page.ts` load function or `+page.server.ts` actions, never in `onMount`
- All mutations must use form actions in `+page.server.ts` with `<form method="POST">` — never use fetch for mutations
- GET requests in load functions must use `fetch` with full URL including protocol and domain
- Load functions must return data object with explicit type matching PageData interface
- Never fetch data in Svelte components — pass data as props from load function
- All API calls must include error handling that returns `{ status: number, error: string }` structure
## Form Actions and Mutations
- Every form action must be named `default`, `create`, `update`, or `delete` — no other names
- Form actions must validate input with Zod schema before processing
- Form actions must return `{ success: boolean, data?: T, error?: string }` structure
- Form actions must catch errors and return typed error response, never throw
- Use `fail(status, { error })` for validation failures, never `throw error`
- Never use `fetch` inside form actions — use server-side libraries directly
## Store Usage
- Stores must be created with `writable()`, `readable()`, or `derived()` from `svelte/store` only
- Store files must export store instance and typed getter function: `export const myStore = writable<Type>(initial); export const getMyStore = () => get(myStore)`
- Never subscribe to stores in components — use `$store` syntax or `{#await}` blocks only
- Global stores are forbidden for page-specific data — use load function return values instead
- Stores must only contain UI state (theme, modals, filters) — never application data
## Component Props and Reactivity
- All Svelte components must have explicit `<script lang="ts">` with typed props using `interface Props`
- Props interface must be exported and used with `let { prop1, prop2 }: Props = $props()`
- Never use two-way binding with `bind:` on props — use event handlers and parent state only
- All event handlers must have explicit parameter types: `(e: Event) => void` not `(e) => {}`
- Reactive declarations must use `$derived` for computed values, never manual `$:` syntax
## Error Handling
- All async functions must have try/catch blocks with typed error handling
- Caught errors must check type: `if (err instanceof Error) { err.message }` — never use `err.message` on `unknown`
- Server-side errors must be logged with `console.error()` and returned as `{ error: string }` to client
- Client-side errors must be displayed in UI or logged to error tracking service, never silently ignored
- HTTP error responses must check `response.ok` before parsing JSON
- Form validation errors must return `fail()` with 400 status, not 500
## Security
- Never hardcode API keys, database URLs, or secrets in `.ts` or `.svelte` files
- All environment variables must be prefixed with `PUBLIC_` for client-side or `VITE_` for build-time only
- Server-only secrets must be in `.env.local` and accessed only in `+page.server.ts` or `+layout.server.ts`
- All user input from forms must be validated with Zod schema before database operations
- All database queries must use parameterized queries or ORM methods — never string concatenation
- CSRF protection is automatic with SvelteKit forms — never disable it
## Testing
- Test files must be named `+page.test.ts` or `ComponentName.test.ts` in same directory as source
- All tests must use Vitest with `describe()` and `it()` blocks
- Load functions must be tested with `import { load } from './+page'` and mocked fetch
- Form actions must be tested by calling action function directly with typed request object
- Components must be tested with `render()` from `@testing-library/svelte` and user interactions
- Never test implementation details — test user-visible behavior only
## Svelte-Specific Patterns
- All pages must have `<svelte:head>` with title and meta tags for SEO
- Use `<svelte:window>` for global event listeners, never `window.addEventListener` in components
- Use `{#if}` blocks for conditional rendering, never ternary operators in markup
- Use `{#each}` with explicit `key` prop for lists: `{#each items as item (item.id)}`
- Never use `{@html}` — sanitize with DOMPurify if HTML is required
- All animations must use `transition:` directive, never manual `setTimeout` animations
## Naming Conventions
- Variables and functions: camelCase (`getUserData`, `isLoading`)
- Components and types: PascalCase (`UserCard`, `UserData`)
- Constants: UPPER_SNAKE_CASE (`MAX_RETRIES`, `API_TIMEOUT`)
- Boolean variables must start with `is`, `has`, or `can`: `isLoading`, `hasError`, `canSubmit`
- Event handlers must start with `on`: `onClick`, `onSubmit`, `onError`
- Svelte stores must end with `Store`: `userStore`, `themeStore`
## Imports and Exports
- Use named exports only — never `export default`
- Group imports: SvelteKit first, then external packages, then local files
- Import types with `import type { Type }` — never mix type and value imports
- Never use wildcard imports `import *` — list specific exports
- Re-export from `src/lib/index.ts` for public API only
## Layout and Nesting
- Use `+layout.svelte` for shared UI across routes, not component wrapping
- Use `+layout.ts` for data needed by all child routes
- Use `+page.ts` for page-specific data only
- Nested layouts inherit parent data automatically — never duplicate fetching
- Use `<slot />` in layouts, never hardcode route-specific content
## Performance
- Never fetch data in `onMount` — use load functions for server-side rendering
- Use `{#await}` blocks for async data, never manual loading states
- Lazy-load heavy components with `<svelte:component this={Component} />`
- Never create stores in components — create in `src/lib/stores/` and import
- Use `export const prerender = true` in `+page.ts` for static pages only
---
> Source: [Codelibrium](https://codelibrium.com) — the marketplace for AI behaviour files.
> Browse multiple rulesets at [codelibrium.com](https://codelibrium.com) or install via CLI:
> `npx codelibrium-cli install <ruleset-name>`