codeforge-dev 1.4.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/.devcontainer/.env +22 -0
- package/.devcontainer/CHANGELOG.md +197 -0
- package/.devcontainer/CLAUDE.md +117 -0
- package/.devcontainer/README.md +222 -0
- package/.devcontainer/config/main-system-prompt.md +502 -0
- package/.devcontainer/config/settings.json +47 -0
- package/.devcontainer/devcontainer.json +94 -0
- package/.devcontainer/features/README.md +113 -0
- package/.devcontainer/features/agent-browser/README.md +65 -0
- package/.devcontainer/features/agent-browser/devcontainer-feature.json +23 -0
- package/.devcontainer/features/agent-browser/install.sh +79 -0
- package/.devcontainer/features/ast-grep/README.md +24 -0
- package/.devcontainer/features/ast-grep/devcontainer-feature.json +24 -0
- package/.devcontainer/features/ast-grep/install.sh +51 -0
- package/.devcontainer/features/ccstatusline/README.md +296 -0
- package/.devcontainer/features/ccstatusline/devcontainer-feature.json +19 -0
- package/.devcontainer/features/ccstatusline/install.sh +290 -0
- package/.devcontainer/features/ccusage/README.md +205 -0
- package/.devcontainer/features/ccusage/devcontainer-feature.json +38 -0
- package/.devcontainer/features/ccusage/install.sh +132 -0
- package/.devcontainer/features/claude-code/README.md +498 -0
- package/.devcontainer/features/claude-code/config/settings.json +36 -0
- package/.devcontainer/features/claude-code/config/system-prompt.md +118 -0
- package/.devcontainer/features/claude-code/config/world-building-sp.md +1432 -0
- package/.devcontainer/features/claude-code/devcontainer-feature.json +42 -0
- package/.devcontainer/features/claude-code/install.sh +466 -0
- package/.devcontainer/features/claude-monitor/README.md +74 -0
- package/.devcontainer/features/claude-monitor/devcontainer-feature.json +38 -0
- package/.devcontainer/features/claude-monitor/install.sh +99 -0
- package/.devcontainer/features/lsp-servers/README.md +85 -0
- package/.devcontainer/features/lsp-servers/devcontainer-feature.json +40 -0
- package/.devcontainer/features/lsp-servers/install.sh +116 -0
- package/.devcontainer/features/mcp-qdrant/CHANGES.md +399 -0
- package/.devcontainer/features/mcp-qdrant/README.md +474 -0
- package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +57 -0
- package/.devcontainer/features/mcp-qdrant/install.sh +295 -0
- package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +129 -0
- package/.devcontainer/features/mcp-reasoner/README.md +177 -0
- package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +20 -0
- package/.devcontainer/features/mcp-reasoner/install.sh +177 -0
- package/.devcontainer/features/mcp-reasoner/poststart-hook.sh +67 -0
- package/.devcontainer/features/notify-hook/README.md +86 -0
- package/.devcontainer/features/notify-hook/devcontainer-feature.json +23 -0
- package/.devcontainer/features/notify-hook/install.sh +38 -0
- package/.devcontainer/features/splitrail/README.md +140 -0
- package/.devcontainer/features/splitrail/devcontainer-feature.json +34 -0
- package/.devcontainer/features/splitrail/install.sh +129 -0
- package/.devcontainer/features/tree-sitter/README.md +138 -0
- package/.devcontainer/features/tree-sitter/devcontainer-feature.json +52 -0
- package/.devcontainer/features/tree-sitter/install.sh +173 -0
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +106 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-file.py +101 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +137 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/.claude-plugin/plugin.json +8 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/SKILL.md +387 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/cli-flags-and-output.md +312 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/sdk-and-mcp.md +569 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/SKILL.md +309 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/compose-services.md +438 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/dockerfile-patterns.md +340 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/SKILL.md +412 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/container-lifecycle.md +388 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/resources-and-security.md +444 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/SKILL.md +344 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/middleware-and-lifespan.md +254 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/pydantic-models.md +245 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/routing-and-dependencies.md +255 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/sse-and-streaming.md +318 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/SKILL.md +345 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/agents-and-tools.md +271 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/models-and-streaming.md +422 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/SKILL.md +220 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/cross-vendor-principles.md +139 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/patterns-and-antipatterns.md +376 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/skill-authoring-patterns.md +356 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/SKILL.md +329 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/advanced-queries.md +314 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/javascript-patterns.md +323 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/python-patterns.md +354 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/schema-and-pragmas.md +326 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/SKILL.md +356 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/ai-sdk-svelte.md +128 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/component-patterns.md +332 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/layercake.md +203 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/migration-guide.md +350 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/runes-and-reactivity.md +328 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/spa-and-routing.md +262 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/svelte-dnd-action.md +181 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/SKILL.md +414 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/fastapi-testing.md +411 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/svelte-testing.md +538 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +110 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/hooks/hooks.json +17 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +108 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272create-pr.md +337 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272new.md +166 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272review-commit.md +290 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272work.md +257 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/plugin.json +8 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/system-prompt.md +184 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/.claude-plugin/plugin.json +6 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/config/planning-instructions.md +14 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/functional-conjuring-map.md +989 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/hooks/hooks.json +33 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/__pycache__/post-enhance-task.cpython-314.pyc +0 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhance-planning.py +71 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-plan.sh +68 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-task.sh +120 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-plan.py +133 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-task.py +253 -0
- package/.devcontainer/scripts/setup-aliases.sh +80 -0
- package/.devcontainer/scripts/setup-config.sh +28 -0
- package/.devcontainer/scripts/setup-irie-claude.sh +32 -0
- package/.devcontainer/scripts/setup-plugins.sh +80 -0
- package/.devcontainer/scripts/setup.sh +58 -0
- package/LICENSE.txt +674 -0
- package/README.md +267 -0
- package/package.json +44 -0
- package/setup.js +83 -0
package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/SKILL.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: svelte5
|
|
3
|
+
description: >-
|
|
4
|
+
This skill should be used when the user asks to "build a Svelte component",
|
|
5
|
+
"create a Svelte app", "use Svelte runes", "set up a SvelteKit SPA",
|
|
6
|
+
"migrate from Svelte 4 to Svelte 5", "manage state with runes",
|
|
7
|
+
"add reactivity in Svelte", "use AI SDK with Svelte",
|
|
8
|
+
"add drag and drop to Svelte", "build charts with LayerCake",
|
|
9
|
+
or discusses Svelte 5 component patterns, snippets, $state, $derived,
|
|
10
|
+
$effect, $props, or SvelteKit routing.
|
|
11
|
+
version: 0.1.0
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Svelte 5 Development
|
|
15
|
+
|
|
16
|
+
## Mental Model
|
|
17
|
+
|
|
18
|
+
Svelte 5 replaces the implicit reactivity compiler with explicit **runes** — function-like signals that declare reactive intent at the call site. Every `$state`, `$derived`, and `$effect` call is a contract: the developer states _what_ is reactive; the compiler handles _how_. This shift eliminates the ambiguity of Svelte 4's `$:` labels where the same syntax could mean derivation, side effect, or conditional execution depending on context.
|
|
19
|
+
|
|
20
|
+
Components communicate through three mechanisms: typed props via `$props()`, callback props replacing `createEventDispatcher`, and snippets replacing slots. Each mechanism is explicit — there is no hidden event bus, no implicit slot projection, and no magic `export let` overloading.
|
|
21
|
+
|
|
22
|
+
SvelteKit provides file-based routing with optional SSR. SPA mode disables server rendering entirely, producing a static shell that handles all routing on the client.
|
|
23
|
+
|
|
24
|
+
Assume Svelte 5 syntax for all new code unless the user explicitly references Svelte 4 or legacy patterns. When modifying an existing codebase that uses Svelte 4 patterns, ask whether to migrate or preserve the existing style. Never mix Svelte 4 and Svelte 5 patterns within the same component — a file should use runes throughout or not at all.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Reactivity with Runes
|
|
29
|
+
|
|
30
|
+
The runes system provides four core primitives: `$state` for mutable values, `$derived` for computed values, `$effect` for side effects, and `$props` for component inputs. A fifth rune, `$inspect`, exists for development-only debugging. Each rune has a specific purpose — choosing the wrong one is the most common source of bugs in Svelte 5 code.
|
|
31
|
+
|
|
32
|
+
### $state — Mutable Reactive State
|
|
33
|
+
|
|
34
|
+
Declare reactive variables with `$state`. The compiler wraps objects and arrays in a proxy for deep tracking — property access registers fine-grained dependencies, and mutations trigger targeted updates.
|
|
35
|
+
|
|
36
|
+
```svelte
|
|
37
|
+
<script>
|
|
38
|
+
let count = $state(0);
|
|
39
|
+
let items = $state([{ name: 'Apple', done: false }]);
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<button onclick={() => count++}>{count}</button>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Primitive values (numbers, strings, booleans) do not use proxies — they track via the signal wrapper itself. Only reassignment triggers reactivity for primitives.
|
|
46
|
+
|
|
47
|
+
Use `$state.raw()` when deep reactivity causes performance issues on large, frequently replaced structures. Raw state tracks only reassignment, not property mutation. This is appropriate for API response caches, immutable datasets, and structures that are always replaced wholesale rather than mutated in place.
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
let rows = $state.raw(fetchLargeDataset());
|
|
51
|
+
rows = rows.filter(r => r.active); // reassignment triggers update
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Use `$state.snapshot()` to produce a plain, non-reactive copy for logging, JSON serialization, `structuredClone`, or passing to external libraries that cannot handle proxies. Without a snapshot, proxy objects may cause unexpected behavior in libraries that iterate or clone objects.
|
|
55
|
+
|
|
56
|
+
### $derived — Computed Values
|
|
57
|
+
|
|
58
|
+
Derived values recalculate synchronously whenever their dependencies change. The synchronous guarantee means derived values are never stale — after updating a `$state`, all `$derived` values reflect the new state immediately with no intermediate inconsistent reads.
|
|
59
|
+
|
|
60
|
+
Prefer `$derived` for any value computable from existing state. Duplicating state that can be derived introduces synchronization bugs and unnecessary complexity.
|
|
61
|
+
|
|
62
|
+
```svelte
|
|
63
|
+
<script>
|
|
64
|
+
let items = $state([{ done: false }, { done: true }]);
|
|
65
|
+
let remaining = $derived(items.filter(i => !i.done).length);
|
|
66
|
+
</script>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
For multi-statement computations that require intermediate variables, use `$derived.by()` with a function body. This maintains the synchronous consistency guarantee while allowing complex logic:
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
let summary = $derived.by(() => {
|
|
73
|
+
const active = items.filter(i => !i.done);
|
|
74
|
+
return `${active.length} of ${items.length} remaining`;
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Derived values can depend on other derived values. The compiler resolves the dependency graph at compile time, so cascading derivations are both safe and efficient. Never use `$effect` to compute a value and assign it to a variable — that pattern loses the synchronous guarantee and creates unnecessary render cycles.
|
|
79
|
+
|
|
80
|
+
### $effect — Side Effects
|
|
81
|
+
|
|
82
|
+
Effects run after the DOM updates whenever their tracked dependencies change. Limit effects to three categories: DOM manipulation, logging/analytics, and synchronization with external systems (APIs, localStorage, WebSockets). If an effect computes a value, it belongs in `$derived` instead.
|
|
83
|
+
|
|
84
|
+
```svelte
|
|
85
|
+
<script>
|
|
86
|
+
let query = $state('');
|
|
87
|
+
|
|
88
|
+
$effect(() => {
|
|
89
|
+
const controller = new AbortController();
|
|
90
|
+
fetch(`/api/search?q=${query}`, { signal: controller.signal });
|
|
91
|
+
return () => controller.abort();
|
|
92
|
+
});
|
|
93
|
+
</script>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Return a cleanup function for teardown logic. The cleanup runs before the next effect execution and when the component is destroyed. Effects cannot be `async` — start async work inside the effect body and use an AbortController or a boolean flag for cancellation.
|
|
97
|
+
|
|
98
|
+
`$effect` also works well for EventSource (SSE) connections — construct in the body, close in cleanup. See `references/runes-and-reactivity.md` for patterns.
|
|
99
|
+
|
|
100
|
+
Use `$effect.pre()` for effects that must run before DOM updates. This is rarely needed — scrolling restoration and DOM measurement before layout changes are the primary use cases.
|
|
101
|
+
|
|
102
|
+
### $inspect — Development-Only Debugging
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
$inspect(count); // logs on change
|
|
106
|
+
$inspect(items).with(console.trace); // custom handler
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`$inspect` is stripped from production builds automatically. Never rely on it for application logic. It exists solely to observe reactive value changes during development without adding `console.log` statements that would need removal.
|
|
110
|
+
|
|
111
|
+
> **Deep dive:** See `references/runes-and-reactivity.md` for proxy tracking semantics, class field patterns, `$state` in classes, destructuring pitfalls, `$effect.root`, and closure tracking rules.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Component Architecture
|
|
116
|
+
|
|
117
|
+
Svelte 5 components have three communication channels: props flow data downward, callback props flow events upward, and snippets allow parents to inject template content into children. Understanding when to use each channel prevents over-engineering and keeps component APIs clean.
|
|
118
|
+
|
|
119
|
+
### Props with $props
|
|
120
|
+
|
|
121
|
+
Declare component inputs using `$props()`. Standard JavaScript destructuring provides defaults, rest collection, and renaming:
|
|
122
|
+
|
|
123
|
+
```svelte
|
|
124
|
+
<script>
|
|
125
|
+
let { title, variant = 'primary', children, ...rest } = $props();
|
|
126
|
+
</script>
|
|
127
|
+
|
|
128
|
+
<div class={variant} {...rest}>
|
|
129
|
+
{@render children()}
|
|
130
|
+
</div>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Rest props (`...rest`) collect all unrecognized attributes for forwarding to DOM elements. This is essential for wrapper components that must preserve the full API of their inner element.
|
|
134
|
+
|
|
135
|
+
Type props with a TypeScript interface for compile-time safety and IDE autocompletion:
|
|
136
|
+
|
|
137
|
+
```svelte
|
|
138
|
+
<script lang="ts">
|
|
139
|
+
interface Props {
|
|
140
|
+
title: string;
|
|
141
|
+
variant?: 'primary' | 'secondary';
|
|
142
|
+
onclick?: (e: MouseEvent) => void;
|
|
143
|
+
}
|
|
144
|
+
let { title, variant = 'primary', onclick }: Props = $props();
|
|
145
|
+
</script>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Mark props as bindable with `$bindable()` when the component API intentionally supports two-way data flow. Only use `$bindable` for form-like components where the parent needs to both read and write a value (inputs, selectors, toggles). Prefer callback props for all other parent-child communication.
|
|
149
|
+
|
|
150
|
+
```svelte
|
|
151
|
+
<script>
|
|
152
|
+
let { value = $bindable('') } = $props();
|
|
153
|
+
</script>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Snippets (Replacing Slots)
|
|
157
|
+
|
|
158
|
+
Snippets replace Svelte 4 slots with explicit, typed template blocks. Unlike slots, snippets are first-class values — they can be stored in variables, passed through multiple layers, and conditionally rendered with standard `{#if}` logic.
|
|
159
|
+
|
|
160
|
+
**Basic children snippet** — content between component tags becomes the `children` prop:
|
|
161
|
+
```svelte
|
|
162
|
+
<!-- Card.svelte -->
|
|
163
|
+
<script>
|
|
164
|
+
let { children } = $props();
|
|
165
|
+
</script>
|
|
166
|
+
<div class="card">
|
|
167
|
+
{@render children()}
|
|
168
|
+
</div>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Parameterized snippets** replace slot props (`let:item`). The parent defines how to render each item; the child controls the iteration and layout:
|
|
172
|
+
```svelte
|
|
173
|
+
<!-- Parent -->
|
|
174
|
+
<List {items}>
|
|
175
|
+
{#snippet row(item)}
|
|
176
|
+
<span>{item.name}</span>
|
|
177
|
+
{/snippet}
|
|
178
|
+
</List>
|
|
179
|
+
|
|
180
|
+
<!-- List.svelte -->
|
|
181
|
+
<script>
|
|
182
|
+
let { items, row } = $props();
|
|
183
|
+
</script>
|
|
184
|
+
{#each items as item}
|
|
185
|
+
{@render row(item)}
|
|
186
|
+
{/each}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Use optional chaining (`{@render footer?.()}`) when a snippet is not required. For default content when a snippet is absent, use an `{#if}` block with a fallback.
|
|
190
|
+
|
|
191
|
+
### Event Handling
|
|
192
|
+
|
|
193
|
+
Svelte 5 uses standard DOM event attributes — no directive syntax. Component-to-parent communication uses callback props following the `on` prefix convention:
|
|
194
|
+
|
|
195
|
+
```svelte
|
|
196
|
+
<!-- DOM events -->
|
|
197
|
+
<button onclick={(e) => handleClick(e)}>Click</button>
|
|
198
|
+
|
|
199
|
+
<!-- Component callback props -->
|
|
200
|
+
<script>
|
|
201
|
+
let { onsubmit } = $props();
|
|
202
|
+
</script>
|
|
203
|
+
<form onsubmit={(e) => { e.preventDefault(); onsubmit(formData); }}>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Convention: prefix callback props with `on` (e.g., `onchange`, `onselect`, `ondelete`). This aligns with DOM event naming and makes the component API predictable. Always use optional chaining when calling callbacks (`onselect?.()`) to handle cases where the parent omits the handler.
|
|
207
|
+
|
|
208
|
+
### Lifecycle
|
|
209
|
+
|
|
210
|
+
`$effect()` replaces `onMount` for most reactive use cases. For non-reactive cleanup (removing global listeners, clearing non-tracked intervals), import `onDestroy` from `svelte`. Import `tick` from `svelte` to await pending DOM updates before reading layout measurements. For imperative component creation outside SvelteKit, import `mount` and `unmount` from `svelte`.
|
|
211
|
+
|
|
212
|
+
> **Deep dive:** See `references/component-patterns.md` for wrapper components, generic typed components, named snippet composition, event forwarding via rest props, and dynamic component rendering.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## State Management
|
|
217
|
+
|
|
218
|
+
State scope should match the smallest boundary that satisfies the requirement. Over-sharing state (making everything global) creates coupling; under-sharing (passing through many prop layers) creates prop drilling. Apply the decision table below to choose the right pattern for each piece of state.
|
|
219
|
+
|
|
220
|
+
### Decision Table
|
|
221
|
+
|
|
222
|
+
| Scope | Pattern | When to Use |
|
|
223
|
+
|-------|---------|-------------|
|
|
224
|
+
| Single component | `$state` in `<script>` | Local UI state — toggles, form fields, loading flags |
|
|
225
|
+
| Parent → children | Props + callback props | Data flows down one or two levels |
|
|
226
|
+
| Subtree (no prop drilling) | `setContext` / `getContext` | Theme, locale, authenticated user, feature flags within a section |
|
|
227
|
+
| Cross-component / global | `.svelte.js` module | Shopping cart, notifications, app-wide settings |
|
|
228
|
+
|
|
229
|
+
### Shared State with .svelte.js Modules
|
|
230
|
+
|
|
231
|
+
Export reactive state from `.svelte.js` files. The Svelte compiler processes runes in these files, enabling `$state` and `$derived` at the module level. Regular `.js` files do not support runes.
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
// lib/stores/cart.svelte.js
|
|
235
|
+
let items = $state([]);
|
|
236
|
+
let total = $derived(items.reduce((sum, i) => sum + i.price * i.qty, 0));
|
|
237
|
+
|
|
238
|
+
export function addItem(product) {
|
|
239
|
+
items.push({ ...product, qty: 1 });
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function getCart() {
|
|
243
|
+
return { get items() { return items; }, get total() { return total; } };
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
```svelte
|
|
248
|
+
<script>
|
|
249
|
+
import { getCart, addItem } from '$lib/stores/cart.svelte.js';
|
|
250
|
+
const cart = getCart();
|
|
251
|
+
</script>
|
|
252
|
+
<p>Total: {cart.total}</p>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Expose state through getter functions or objects with getter properties. Direct export of `$state` variables loses reactivity because the importing module receives the current value, not the reactive signal. This is the most common mistake when building shared state in Svelte 5 — always wrap in a getter.
|
|
256
|
+
|
|
257
|
+
### Context API
|
|
258
|
+
|
|
259
|
+
Context scopes state to a component subtree without prop drilling. Context values set with `setContext` during component initialization are available to all descendants via `getContext`. Context is ideal for dependency injection patterns — a layout component provides a theme, and any descendant reads it without explicit prop passing.
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
// Parent
|
|
263
|
+
import { setContext } from 'svelte';
|
|
264
|
+
let theme = $state('light');
|
|
265
|
+
setContext('theme', () => theme);
|
|
266
|
+
|
|
267
|
+
// Descendant
|
|
268
|
+
import { getContext } from 'svelte';
|
|
269
|
+
const getTheme = getContext('theme');
|
|
270
|
+
// Access: getTheme()
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Pass a getter function (not the raw value) to preserve reactivity through context. Passing the value directly captures a snapshot at initialization time and never updates.
|
|
274
|
+
|
|
275
|
+
> **Deep dive:** See `references/runes-and-reactivity.md` for class-based reactive stores and `$effect.root` for advanced teardown patterns.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## SvelteKit SPA Configuration
|
|
280
|
+
|
|
281
|
+
Three changes convert a SvelteKit project to a client-only single-page application: install `adapter-static`, configure a fallback page, and disable SSR at the root layout. This produces a static shell that handles all routing on the client.
|
|
282
|
+
|
|
283
|
+
```js
|
|
284
|
+
// svelte.config.js
|
|
285
|
+
import adapter from '@sveltejs/adapter-static';
|
|
286
|
+
|
|
287
|
+
export default {
|
|
288
|
+
kit: {
|
|
289
|
+
adapter: adapter({ fallback: '200.html' }),
|
|
290
|
+
prerender: { entries: [] }
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
```js
|
|
296
|
+
// src/routes/+layout.js
|
|
297
|
+
export const ssr = false;
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
The fallback page name depends on the hosting platform — `200.html` for Surge and most static hosts, `index.html` for Netlify with a `_redirects` file, or `404.html` for GitHub Pages. The fallback serves the SPA shell for all routes not matched by a prerendered static file.
|
|
301
|
+
|
|
302
|
+
Set `prerender.entries` to an empty array to disable automatic prerendering. For selective prerendering, export `prerender = true` from individual `+page.js` files — useful for marketing pages or SEO-critical content that benefits from static HTML.
|
|
303
|
+
|
|
304
|
+
In SPA mode, only `+page.js` and `+layout.js` load functions work. Server-side load functions (`.server.js`) are unavailable. All data fetching occurs in client-side load functions or in component `$effect` blocks.
|
|
305
|
+
|
|
306
|
+
> **Deep dive:** See `references/spa-and-routing.md` for file-based routing patterns, dynamic parameters, route groups, client-only load functions, invalidation, navigation helpers, and prerender configuration.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Correct Svelte 5 Patterns
|
|
311
|
+
|
|
312
|
+
Quick-reference table for the ten most common pattern migrations. Each row shows the legacy approach and the modern replacement:
|
|
313
|
+
|
|
314
|
+
| Svelte 4 (Legacy) | Svelte 5 (Runes) |
|
|
315
|
+
|-|-|
|
|
316
|
+
| `let count = 0;` (implicit reactivity) | `let count = $state(0);` |
|
|
317
|
+
| `$: doubled = count * 2;` | `let doubled = $derived(count * 2);` |
|
|
318
|
+
| `$: { console.log(count); }` | `$effect(() => { console.log(count); });` |
|
|
319
|
+
| `export let title;` | `let { title } = $props();` |
|
|
320
|
+
| `<slot />` | `{@render children()}` |
|
|
321
|
+
| `<slot name="header" />` | `{#snippet header()}...{/snippet}` + `{@render header()}` |
|
|
322
|
+
| `createEventDispatcher()` | Callback props: `let { onclick } = $props();` |
|
|
323
|
+
| `on:click={handler}` | `onclick={handler}` |
|
|
324
|
+
| `<svelte:component this={Comp} />` | `<Comp />` (direct dynamic reference) |
|
|
325
|
+
| `bind:value` (implicit) | `let { value = $bindable() } = $props();` |
|
|
326
|
+
|
|
327
|
+
When encountering Svelte 4 patterns in an existing codebase, do not silently convert them. Ask whether the component should be migrated or whether the existing style should be preserved for consistency with the rest of the project.
|
|
328
|
+
|
|
329
|
+
> **Complete migration guide:** See `references/migration-guide.md` for full before/after code blocks with rationale and edge cases for each of the ten patterns.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Ambiguity Policy
|
|
334
|
+
|
|
335
|
+
These defaults apply when the user does not specify a preference. State them when making an assumption so the user can override:
|
|
336
|
+
|
|
337
|
+
- **New components:** Default to Svelte 5 runes syntax. Do not use legacy reactive declarations (`$:`) or `export let`. State the assumption if the project context is unclear.
|
|
338
|
+
- **Existing codebase edits:** If the file contains Svelte 4 patterns (`$:`, `export let`, `<slot>`), ask whether to migrate the component or match the existing style before making changes.
|
|
339
|
+
- **State scope:** Default to component-local `$state`. Escalate to `.svelte.js` modules only when the user specifies cross-component sharing or the requirement clearly involves multiple unrelated components accessing the same data.
|
|
340
|
+
- **SPA vs SSR:** Default to SPA configuration (`ssr = false`) unless the user mentions server rendering, prerendering multiple routes, SEO requirements, or content that must be indexed by search engines.
|
|
341
|
+
- **TypeScript:** Default to TypeScript (`lang="ts"`) unless the project uses plain JavaScript files throughout. Check existing `.svelte` files for `lang` attributes before deciding.
|
|
342
|
+
- **Styling:** Default to component-scoped `<style>` blocks. Suggest Tailwind only if the project already includes a Tailwind configuration.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Reference Files
|
|
347
|
+
|
|
348
|
+
| File | Contents |
|
|
349
|
+
|------|----------|
|
|
350
|
+
| `references/runes-and-reactivity.md` | Proxy tracking semantics, $state deep/raw/snapshot, $derived.by cascading, $effect timing/cleanup/async, class field patterns, destructuring pitfalls, $effect.root |
|
|
351
|
+
| `references/component-patterns.md` | Props patterns with TypeScript, snippet composition (basic/named/parameterized), event handling and forwarding, wrapper components, generic typed components, dynamic rendering |
|
|
352
|
+
| `references/spa-and-routing.md` | Full SPA config, file-based routing with dynamic params, route groups, client-only load functions, invalidation, prerendering in SPA mode, navigation helpers and lifecycle hooks |
|
|
353
|
+
| `references/migration-guide.md` | 10 migration patterns with complete Svelte 4 → Svelte 5 before/after code, rationale for each change, and edge cases to handle during conversion |
|
|
354
|
+
| `references/ai-sdk-svelte.md` | @ai-sdk/svelte class-based API (Chat, Completion, StructuredObject), createAIContext for shared state, getter syntax for reactive options, destructuring pitfalls |
|
|
355
|
+
| `references/svelte-dnd-action.md` | svelte-dnd-action drag-and-drop with use:dndzone, consider/finalize events, drag handles, Svelte 5 event syntax, shadow item filtering, version requirements |
|
|
356
|
+
| `references/layercake.md` | LayerCake headless chart framework, scale-based coordinate system, layout components (Svg/Html/Canvas/WebGl), runes incompatibility and workarounds, multi-layer composition |
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# AI SDK Svelte — Reference
|
|
2
|
+
|
|
3
|
+
## Mental Model
|
|
4
|
+
|
|
5
|
+
The `@ai-sdk/svelte` package provides class-based state management for AI-powered UI. Three classes cover the primary use cases: `Chat` for conversational interfaces, `Completion` for single-prompt text generation, and `StructuredObject` for streaming typed JSON. Each class encapsulates connection state, loading indicators, error handling, and the accumulated response — eliminating manual fetch/state synchronization.
|
|
6
|
+
|
|
7
|
+
These classes integrate with Svelte 5 reactivity through their properties. Instances expose reactive properties (messages, input, status, error) that update as the server streams tokens. The classes handle the streaming protocol internally; component code reads properties and calls methods.
|
|
8
|
+
|
|
9
|
+
> Official documentation covers server-side route handlers, provider configuration, and model selection: <https://sdk.vercel.ai/docs>
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Core Classes
|
|
14
|
+
|
|
15
|
+
### Chat
|
|
16
|
+
|
|
17
|
+
Manages a multi-turn conversation with message history, automatic input handling, and abort support.
|
|
18
|
+
|
|
19
|
+
```svelte
|
|
20
|
+
<script lang="ts">
|
|
21
|
+
import { Chat } from '@ai-sdk/svelte';
|
|
22
|
+
|
|
23
|
+
const chat = new Chat({ api: '/api/chat' });
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<ul>
|
|
27
|
+
{#each chat.messages as message}
|
|
28
|
+
<li>{message.role}: {message.content}</li>
|
|
29
|
+
{/each}
|
|
30
|
+
</ul>
|
|
31
|
+
|
|
32
|
+
<form onsubmit={chat.handleSubmit}>
|
|
33
|
+
<input bind:value={chat.input} />
|
|
34
|
+
<button type="submit">Send</button>
|
|
35
|
+
</form>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Key properties: `messages`, `input`, `status`, `error`, `isLoading`.
|
|
39
|
+
Key methods: `handleSubmit`, `append`, `reload`, `stop`, `setMessages`.
|
|
40
|
+
|
|
41
|
+
### Completion
|
|
42
|
+
|
|
43
|
+
Manages single-prompt text completion without message history.
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
import { Completion } from '@ai-sdk/svelte';
|
|
47
|
+
|
|
48
|
+
const completion = new Completion({ api: '/api/completion' });
|
|
49
|
+
// completion.completion — the generated text
|
|
50
|
+
// completion.complete(prompt) — trigger generation
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### StructuredObject
|
|
54
|
+
|
|
55
|
+
Streams a typed JSON object as tokens arrive, providing partial results during generation.
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
import { StructuredObject } from '@ai-sdk/svelte';
|
|
59
|
+
|
|
60
|
+
const obj = new StructuredObject({ api: '/api/object', schema: myZodSchema });
|
|
61
|
+
// obj.object — the (partial) parsed object
|
|
62
|
+
// obj.submit(input) — trigger generation
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Shared State with createAIContext
|
|
68
|
+
|
|
69
|
+
`createAIContext()` shares a `Chat` (or other class) instance across a component subtree via Svelte context, avoiding prop drilling for chat UIs split across message list, input, and status components.
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
// Layout or parent component
|
|
73
|
+
import { createAIContext } from '@ai-sdk/svelte';
|
|
74
|
+
|
|
75
|
+
const context = createAIContext({ chat: new Chat({ api: '/api/chat' }) });
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Descendant components retrieve the shared instance with `getAIContext()`.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Svelte 5 Integration
|
|
83
|
+
|
|
84
|
+
### Pass Getters for Reactive Options
|
|
85
|
+
|
|
86
|
+
Script blocks in Svelte 5 run once. Constructor options that depend on reactive values must use getter syntax so the class reads the current value on each access:
|
|
87
|
+
|
|
88
|
+
```svelte
|
|
89
|
+
<script>
|
|
90
|
+
let model = $state('gpt-4o');
|
|
91
|
+
|
|
92
|
+
// Correct — getter re-evaluates on each internal read
|
|
93
|
+
const chat = new Chat({
|
|
94
|
+
api: '/api/chat',
|
|
95
|
+
body: { get model() { return model; } }
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Wrong — captures the initial value of model, never updates
|
|
99
|
+
const chat2 = new Chat({
|
|
100
|
+
api: '/api/chat',
|
|
101
|
+
body: { model: model }
|
|
102
|
+
});
|
|
103
|
+
</script>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Do Not Destructure Reactive Properties
|
|
107
|
+
|
|
108
|
+
Class instances expose reactive properties through getters on the prototype. Destructuring copies the current value into a plain variable, severing reactivity:
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
// Wrong — greeting loses reactivity
|
|
112
|
+
const { messages, input } = chat;
|
|
113
|
+
|
|
114
|
+
// Correct — always read from the instance
|
|
115
|
+
chat.messages
|
|
116
|
+
chat.input
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Reactive State for Custom Data Alongside Chat
|
|
120
|
+
|
|
121
|
+
Combine `$state` with Chat class properties freely. The Chat instance manages its own reactivity; local `$state` handles additional UI concerns:
|
|
122
|
+
|
|
123
|
+
```svelte
|
|
124
|
+
<script>
|
|
125
|
+
const chat = new Chat({ api: '/api/chat' });
|
|
126
|
+
let sidebarOpen = $state(false);
|
|
127
|
+
</script>
|
|
128
|
+
```
|