cfsa-antigravity 2.9.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cfsa-antigravity",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "CFSA Pipeline — Constraint-First Specification Architecture for AI agents. Production-grade from line one.",
5
5
  "scripts": {
6
6
  "changeset": "changeset",
@@ -1,6 +1,6 @@
1
1
  # Kit Sync State
2
2
 
3
3
  upstream: https://github.com/RepairYourTech/cfsa-antigravity
4
- last_synced_commit: 9f4ba4f09f8234f0e81f568f66f6394148c0e383
5
- last_synced_at: 2026-03-17T05:20:16Z
6
- kit_version: 2.9.0
4
+ last_synced_commit: e60781547ac48627470760d78942ad063e22c9dc
5
+ last_synced_at: 2026-03-17T15:19:28Z
6
+ kit_version: 2.10.0
@@ -55,6 +55,7 @@ When a stack key matches a value pattern (case-insensitive), install the listed
55
55
  | `FRONTEND_FRAMEWORK` | `*astro*` | `stack/frameworks/astro-framework` | `astro-framework` |
56
56
  | `FRONTEND_FRAMEWORK` | `*next*` | `stack/frameworks/nextjs` | `nextjs` |
57
57
  | `FRONTEND_FRAMEWORK` | `*svelte*` OR `*sveltekit*` | `stack/frameworks/sveltekit` | `sveltekit` |
58
+ | `FRONTEND_FRAMEWORK` | `*svelte*` OR `*sveltekit*` | `stack/frameworks/svelte5` | `svelte5` |
58
59
  | `FRONTEND_FRAMEWORK` | `*nuxt*` | `stack/frameworks/nuxt` | `nuxt` |
59
60
  | `BACKEND_FRAMEWORK` | `*hono*` | `stack/frameworks/hono` | `hono` |
60
61
  | `BACKEND_FRAMEWORK` | `*fastapi*` | `stack/frameworks/fastapi` | `fastapi` |
@@ -94,6 +95,7 @@ When a stack key matches a value pattern (case-insensitive), install the listed
94
95
  | `CSS_FRAMEWORK` | `*sass*` OR `*scss*` | `stack/css/sass-scss` | `sass-scss` |
95
96
  | `UI_LIBRARY` | `*shadcn*` | `stack/ui/shadcn-ui` | `shadcn-ui` |
96
97
  | `UI_LIBRARY` | `*react-flow*` OR `*xyflow*` | `stack/ui/react-flow` | `react-flow` |
98
+ | `UI_LIBRARY` | `*svelte-flow*` OR `*svelteflow*` OR `*xyflow*` | `stack/ui/svelte-flow` | `svelte-flow` |
97
99
  | `FRONTEND_FRAMEWORK` | `*react*` | `stack/ui/react-best-practices` | `react-best-practices` |
98
100
  | `FRONTEND_FRAMEWORK` | `*react*` | `stack/ui/react-composition-patterns` | `react-composition-patterns` |
99
101
  | `DESIGN_DIRECTION` | `*` (any confirmed value) | Fills `{{PLACEHOLDER}}`s in `.agent/skills/brand-guidelines/SKILL.md` in-place | `brand-guidelines` (in-place fill, not copy) |
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: svelte5-best-practices
3
+ description: "Svelte 5 runes, snippets, SvelteKit patterns, and modern best practices for TypeScript and component development. Use when writing, reviewing, or refactoring Svelte 5 components and SvelteKit applications. Triggers on: Svelte components, runes ($state, $derived, $effect, $props, $bindable, $inspect), snippets ({#snippet}, {@render}), event handling, SvelteKit data loading, form actions, Svelte 4 to Svelte 5 migration, store to rune migration, slots to snippets migration, TypeScript props typing, generic components, SSR state isolation, performance optimization, or component testing."
4
+ license: MIT
5
+ metadata:
6
+ author: ejirocodes
7
+ version: '1.0.0'
8
+ ---
9
+
10
+ # Svelte 5 Best Practices
11
+
12
+ ## Quick Reference
13
+
14
+ | Topic | When to Use | Reference |
15
+ |-------|-------------|-----------|
16
+ | **Runes** | $state, $derived, $effect, $props, $bindable, $inspect | [runes.md](references/runes.md) |
17
+ | **Snippets** | Replacing slots, {#snippet}, {@render} | [snippets.md](references/snippets.md) |
18
+ | **Events** | onclick handlers, callback props, context API | [events.md](references/events.md) |
19
+ | **TypeScript** | Props typing, generic components | [typescript.md](references/typescript.md) |
20
+ | **Migration** | Svelte 4 to 5, stores to runes | [migration.md](references/migration.md) |
21
+ | **SvelteKit** | Load functions, form actions, SSR, page typing | [sveltekit.md](references/sveltekit.md) |
22
+ | **Performance** | Universal reactivity, avoiding over-reactivity, streaming | [performance.md](references/performance.md) |
23
+
24
+ ## Essential Patterns
25
+
26
+ ### Reactive State
27
+
28
+ ```svelte
29
+ <script>
30
+ let count = $state(0); // Reactive state
31
+ let doubled = $derived(count * 2); // Computed value
32
+ </script>
33
+ ```
34
+
35
+ ### Component Props
36
+
37
+ ```svelte
38
+ <script>
39
+ let { name, count = 0 } = $props();
40
+ let { value = $bindable() } = $props(); // Two-way binding
41
+ </script>
42
+ ```
43
+
44
+ ### Snippets (replacing slots)
45
+
46
+ ```svelte
47
+ <script>
48
+ let { children, header } = $props();
49
+ </script>
50
+
51
+ {@render header?.()}
52
+ {@render children()}
53
+ ```
54
+
55
+ ### Event Handlers
56
+
57
+ ```svelte
58
+ <!-- Svelte 5: use onclick, not on:click -->
59
+ <button onclick={() => count++}>Click</button>
60
+ ```
61
+
62
+ ### Callback Props (replacing createEventDispatcher)
63
+
64
+ ```svelte
65
+ <script>
66
+ let { onclick } = $props();
67
+ </script>
68
+
69
+ <button onclick={() => onclick?.({ data })}>Click</button>
70
+ ```
71
+
72
+ ## Common Mistakes
73
+
74
+ 1. **Using `let` without `$state`** - Variables are not reactive without `$state()`
75
+ 2. **Using `$effect` for derived values** - Use `$derived` instead
76
+ 3. **Using `on:click` syntax** - Use `onclick` in Svelte 5
77
+ 4. **Using `createEventDispatcher`** - Use callback props instead
78
+ 5. **Using `<slot>`** - Use snippets with `{@render}`
79
+ 6. **Forgetting `$bindable()`** - Required for `bind:` to work
80
+ 7. **Setting module-level state in SSR** - Causes cross-request leaks
81
+ 8. **Sequential awaits in load functions** - Use `Promise.all` for parallel requests
@@ -0,0 +1,353 @@
1
+ # Svelte 5 Events Reference
2
+
3
+ ## Table of Contents
4
+ - [Event Handler Syntax](#event-handler-syntax)
5
+ - [Callback Props Pattern](#callback-props-pattern)
6
+ - [Context API](#context-api)
7
+
8
+ ---
9
+
10
+ ## Event Handler Syntax
11
+
12
+ Svelte 5 replaces `on:click` directive syntax with standard HTML attribute syntax `onclick`.
13
+
14
+ ### Basic Event Handlers
15
+
16
+ **Svelte 4:**
17
+ ```svelte
18
+ <button on:click={handleClick}>Click</button>
19
+ <input on:input={handleInput} />
20
+ <form on:submit={handleSubmit}>...</form>
21
+ ```
22
+
23
+ **Svelte 5:**
24
+ ```svelte
25
+ <button onclick={handleClick}>Click</button>
26
+ <input oninput={handleInput} />
27
+ <form onsubmit={handleSubmit}>...</form>
28
+ ```
29
+
30
+ ### Event Modifiers Migration
31
+
32
+ Event modifiers no longer exist. Use wrapper functions:
33
+
34
+ **Svelte 4:**
35
+ ```svelte
36
+ <form on:submit|preventDefault={handleSubmit}>...</form>
37
+ <button on:click|stopPropagation={handleClick}>...</button>
38
+ ```
39
+
40
+ **Svelte 5:**
41
+ ```svelte
42
+ <script>
43
+ function handleSubmit(event) {
44
+ event.preventDefault();
45
+ // ... handle form
46
+ }
47
+
48
+ function handleClick(event) {
49
+ event.stopPropagation();
50
+ // ... handle click
51
+ }
52
+ </script>
53
+
54
+ <form onsubmit={handleSubmit}>...</form>
55
+ <button onclick={handleClick}>...</button>
56
+ ```
57
+
58
+ ### Capture, Passive, and NonPassive
59
+
60
+ ```svelte
61
+ <!-- Capture phase -->
62
+ <div onclickcapture={handleCapture}>
63
+ <button onclick={handleClick}>Click</button>
64
+ </div>
65
+
66
+ <!-- Passive listener -->
67
+ <div ontouchstartpassive={handleTouch}>...</div>
68
+
69
+ <!-- Non-passive -->
70
+ <div ontouchmovenonpassive={(e) => e.preventDefault()}>...</div>
71
+ ```
72
+
73
+ ### Inline Handlers
74
+
75
+ ```svelte
76
+ <button onclick={() => count++}>Count: {count}</button>
77
+ <input oninput={(e) => name = e.target.value} />
78
+ ```
79
+
80
+ ### Event Handler Shorthand
81
+
82
+ ```svelte
83
+ <script>
84
+ function onclick(event) {
85
+ console.log('Clicked!', event);
86
+ }
87
+ </script>
88
+
89
+ <button {onclick}>Click</button>
90
+ ```
91
+
92
+ ### Spreading Event Handlers
93
+
94
+ ```svelte
95
+ <script>
96
+ let handlers = {
97
+ onclick: () => console.log('clicked'),
98
+ onmouseenter: () => console.log('entered'),
99
+ onmouseleave: () => console.log('left')
100
+ };
101
+ </script>
102
+
103
+ <button {...handlers}>Hover or Click</button>
104
+ ```
105
+
106
+ ### Multiple Handlers for Same Event
107
+
108
+ In Svelte 5, combine logic into one handler:
109
+
110
+ ```svelte
111
+ <script>
112
+ function handleClick(event) {
113
+ handler1(event);
114
+ handler2(event);
115
+ }
116
+ </script>
117
+
118
+ <button onclick={handleClick}>...</button>
119
+ ```
120
+
121
+ ### TypeScript Event Typing
122
+
123
+ ```svelte
124
+ <script lang="ts">
125
+ function handleClick(event: MouseEvent) {
126
+ console.log(event.clientX, event.clientY);
127
+ }
128
+
129
+ function handleInput(event: Event) {
130
+ const target = event.target as HTMLInputElement;
131
+ console.log(target.value);
132
+ }
133
+
134
+ function handleSubmit(event: SubmitEvent) {
135
+ event.preventDefault();
136
+ const formData = new FormData(event.currentTarget as HTMLFormElement);
137
+ }
138
+ </script>
139
+ ```
140
+
141
+ ---
142
+
143
+ ## Callback Props Pattern
144
+
145
+ Svelte 5 deprecates `createEventDispatcher` in favor of callback props for component-to-parent communication.
146
+
147
+ ### Basic Event Pattern
148
+
149
+ **Svelte 4:**
150
+ ```svelte
151
+ <!-- Button.svelte -->
152
+ <script>
153
+ import { createEventDispatcher } from 'svelte';
154
+ const dispatch = createEventDispatcher();
155
+ </script>
156
+
157
+ <button on:click={() => dispatch('click', { timestamp: Date.now() })}>Click</button>
158
+
159
+ <!-- Parent.svelte -->
160
+ <Button on:click={(e) => console.log(e.detail)} />
161
+ ```
162
+
163
+ **Svelte 5:**
164
+ ```svelte
165
+ <!-- Button.svelte -->
166
+ <script>
167
+ let { onclick } = $props();
168
+ </script>
169
+
170
+ <button onclick={() => onclick?.({ timestamp: Date.now() })}>Click</button>
171
+
172
+ <!-- Parent.svelte -->
173
+ <Button onclick={(data) => console.log(data)} />
174
+ ```
175
+
176
+ ### Multiple Callbacks
177
+
178
+ ```svelte
179
+ <!-- Dialog.svelte -->
180
+ <script>
181
+ let { onconfirm, oncancel, onclose } = $props();
182
+ </script>
183
+
184
+ <dialog>
185
+ <button onclick={() => onconfirm?.()}>Confirm</button>
186
+ <button onclick={() => oncancel?.()}>Cancel</button>
187
+ <button onclick={() => onclose?.()}>X</button>
188
+ </dialog>
189
+
190
+ <!-- Parent.svelte -->
191
+ <Dialog
192
+ onconfirm={() => save()}
193
+ oncancel={() => reset()}
194
+ onclose={() => visible = false}
195
+ />
196
+ ```
197
+
198
+ ### Typed Callbacks with TypeScript
199
+
200
+ ```svelte
201
+ <script lang="ts">
202
+ interface Props {
203
+ value?: string;
204
+ onsearch?: (query: string) => void;
205
+ onchange?: (value: string) => void;
206
+ onclear?: () => void;
207
+ }
208
+
209
+ let { value = '', onsearch, onchange, onclear }: Props = $props();
210
+
211
+ function handleInput(e: Event) {
212
+ const newValue = (e.target as HTMLInputElement).value;
213
+ value = newValue;
214
+ onchange?.(newValue);
215
+ }
216
+ </script>
217
+ ```
218
+
219
+ ### Forwarding Native Events
220
+
221
+ ```svelte
222
+ <script lang="ts">
223
+ import type { MouseEventHandler } from 'svelte/elements';
224
+
225
+ interface Props {
226
+ onclick?: MouseEventHandler<HTMLButtonElement>;
227
+ children: import('svelte').Snippet;
228
+ }
229
+
230
+ let { onclick, children, ...rest }: Props = $props();
231
+ </script>
232
+
233
+ <button {onclick} {...rest}>{@render children()}</button>
234
+ ```
235
+
236
+ ---
237
+
238
+ ## Context API
239
+
240
+ Context functions must be called synchronously during component initialization.
241
+
242
+ ### Correct Context Usage
243
+
244
+ ```svelte
245
+ <script>
246
+ import { setContext, getContext } from 'svelte';
247
+
248
+ // These run during initialization - CORRECT
249
+ setContext('theme', 'dark');
250
+ const theme = getContext('theme');
251
+
252
+ // INCORRECT - in $effect or callback
253
+ // $effect(() => { setContext('theme', 'dark'); }); // ERROR
254
+ </script>
255
+ ```
256
+
257
+ ### Reactive Context Values
258
+
259
+ Pass `$state` objects for reactive context:
260
+
261
+ ```svelte
262
+ <!-- Provider.svelte -->
263
+ <script>
264
+ import { setContext } from 'svelte';
265
+
266
+ let theme = $state('light');
267
+
268
+ setContext('theme', {
269
+ get current() { return theme; },
270
+ toggle() { theme = theme === 'light' ? 'dark' : 'light'; }
271
+ });
272
+
273
+ let { children } = $props();
274
+ </script>
275
+
276
+ {@render children()}
277
+
278
+ <!-- Consumer.svelte -->
279
+ <script>
280
+ import { getContext } from 'svelte';
281
+ const themeContext = getContext('theme');
282
+ </script>
283
+
284
+ <p>Theme: {themeContext.current}</p>
285
+ <button onclick={themeContext.toggle}>Toggle</button>
286
+ ```
287
+
288
+ ### Type-Safe Context Pattern
289
+
290
+ ```ts
291
+ // context.ts
292
+ import { setContext, getContext } from 'svelte';
293
+
294
+ const THEME_KEY = Symbol('theme');
295
+
296
+ interface ThemeContext {
297
+ current: 'light' | 'dark';
298
+ toggle: () => void;
299
+ }
300
+
301
+ export function setThemeContext(context: ThemeContext) {
302
+ setContext(THEME_KEY, context);
303
+ }
304
+
305
+ export function getThemeContext(): ThemeContext {
306
+ const context = getContext<ThemeContext>(THEME_KEY);
307
+ if (!context) throw new Error('Theme context not found');
308
+ return context;
309
+ }
310
+ ```
311
+
312
+ ### Avoid Generic Keys
313
+
314
+ ```svelte
315
+ <script>
316
+ // Option 1: Symbol
317
+ const USER_KEY = Symbol('user');
318
+ setContext(USER_KEY, userData);
319
+
320
+ // Option 2: Unique string
321
+ setContext('myapp:user', userData);
322
+
323
+ // Option 3: Object key
324
+ const userKey = {};
325
+ setContext(userKey, userData);
326
+ </script>
327
+ ```
328
+
329
+ ### hasContext Check
330
+
331
+ ```svelte
332
+ <script>
333
+ import { hasContext, getContext } from 'svelte';
334
+
335
+ const hasTheme = hasContext('theme');
336
+ const theme = hasTheme ? getContext('theme') : { current: 'light' };
337
+ </script>
338
+ ```
339
+
340
+ ### Context Boundaries
341
+
342
+ Context flows down the component tree:
343
+
344
+ ```svelte
345
+ <!-- Parent.svelte -->
346
+ <script>
347
+ import { getContext, setContext } from 'svelte';
348
+ const level = getContext('level'); // 0
349
+ setContext('level', level + 1); // Override for children
350
+ </script>
351
+
352
+ <Child /> <!-- Will see level = 1 -->
353
+ ```