ima2-gen 2.0.15 → 2.0.16

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.
Files changed (125) hide show
  1. package/README.md +30 -0
  2. package/bin/commands/skill.js +336 -17
  3. package/bin/ima2.js +22 -2
  4. package/bin/lib/doctor-checks.js +6 -4
  5. package/config.js +1 -0
  6. package/docs/CLI.md +25 -3
  7. package/docs/PROMPT_STUDIO.ko.md +29 -0
  8. package/docs/PROMPT_STUDIO.md +31 -0
  9. package/docs/migration/runtime-test-inventory.md +7 -1
  10. package/lib/agentImageVideoGen.js +8 -0
  11. package/lib/agentQueueStore.js +36 -10
  12. package/lib/agentQueueWorker.js +79 -7
  13. package/lib/agentRuntime.js +2 -0
  14. package/lib/assetLifecycle.js +40 -8
  15. package/lib/canvasVersionStore.js +86 -0
  16. package/lib/cardNewsGenerator.js +37 -3
  17. package/lib/cardNewsJobStore.js +10 -0
  18. package/lib/cardNewsManifestStore.js +6 -12
  19. package/lib/cardNewsPath.js +25 -0
  20. package/lib/db.js +2 -0
  21. package/lib/generatePipeline.js +474 -0
  22. package/lib/generationInputValidation.js +32 -0
  23. package/lib/grokImageCore.js +18 -1
  24. package/lib/historyIndex.js +11 -4
  25. package/lib/historyList.js +3 -0
  26. package/lib/imageMetadata.js +3 -0
  27. package/lib/inflight.js +30 -3
  28. package/lib/multimodePipeline.js +462 -0
  29. package/lib/nodeGeneration.js +440 -0
  30. package/lib/nodeValidation.js +23 -0
  31. package/lib/oauthProxy/generators.js +3 -246
  32. package/lib/oauthProxy/multimodeGenerators.js +251 -0
  33. package/lib/routeHelpers.js +9 -2
  34. package/package.json +2 -2
  35. package/routes/agent.js +4 -4
  36. package/routes/canvasVersions.js +21 -1
  37. package/routes/cardNews.js +2 -1
  38. package/routes/edit.js +25 -9
  39. package/routes/events.js +5 -1
  40. package/routes/generate.js +2 -481
  41. package/routes/keys.js +31 -39
  42. package/routes/multimode.js +2 -502
  43. package/routes/nodes.js +3 -448
  44. package/routes/video.js +12 -3
  45. package/routes/videoExtended.js +19 -4
  46. package/server.js +53 -1
  47. package/skills/ima2/SKILL.md +204 -0
  48. package/skills/ima2-front/SKILL.md +611 -0
  49. package/skills/ima2-front/references/a11y-patterns.md +134 -0
  50. package/skills/ima2-front/references/aesthetics.md +327 -0
  51. package/skills/ima2-front/references/anti-slop.md +241 -0
  52. package/skills/ima2-front/references/asset-requirements.md +431 -0
  53. package/skills/ima2-front/references/brand-asset-sourcing.md +122 -0
  54. package/skills/ima2-front/references/color-system.md +132 -0
  55. package/skills/ima2-front/references/consistency-locks.md +20 -0
  56. package/skills/ima2-front/references/crud-ui.md +53 -0
  57. package/skills/ima2-front/references/dropdown-layer.md +110 -0
  58. package/skills/ima2-front/references/i18n-global.md +104 -0
  59. package/skills/ima2-front/references/iterative-design.md +90 -0
  60. package/skills/ima2-front/references/korea-2026.md +174 -0
  61. package/skills/ima2-front/references/layout-discipline.md +161 -0
  62. package/skills/ima2-front/references/liquid-glass.md +181 -0
  63. package/skills/ima2-front/references/logo-sections.md +194 -0
  64. package/skills/ima2-front/references/mobile-ux.md +144 -0
  65. package/skills/ima2-front/references/performance-budget.md +106 -0
  66. package/skills/ima2-front/references/preflight-full.md +58 -0
  67. package/skills/ima2-front/references/product-density.md +53 -0
  68. package/skills/ima2-front/references/prototype-variants.md +54 -0
  69. package/skills/ima2-front/references/reference-capture.md +120 -0
  70. package/skills/ima2-front/references/responsive-viewport.md +139 -0
  71. package/skills/ima2-front/references/seo-baseline.md +123 -0
  72. package/skills/ima2-front/references/soft-3d-asset-gates.md +70 -0
  73. package/skills/ima2-front/references/stacks/astro.md +204 -0
  74. package/skills/ima2-front/references/stacks/mobile-native.md +281 -0
  75. package/skills/ima2-front/references/stacks/nextjs.md +219 -0
  76. package/skills/ima2-front/references/stacks/react.md +264 -0
  77. package/skills/ima2-front/references/stacks/svelte.md +235 -0
  78. package/skills/ima2-front/references/stacks/vanilla.md +226 -0
  79. package/skills/ima2-front/references/theme-switching.md +82 -0
  80. package/skills/ima2-front/references/top-bar.md +126 -0
  81. package/skills/ima2-front/references/typography-wrapping.md +270 -0
  82. package/skills/ima2-front/references/ux-writing-ko.md +62 -0
  83. package/skills/ima2-front/references/visual-verification.md +102 -0
  84. package/skills/ima2-uiux/SKILL.md +477 -0
  85. package/skills/ima2-uiux/references/anti-slop-judgment.md +39 -0
  86. package/skills/ima2-uiux/references/color-system.md +80 -0
  87. package/skills/ima2-uiux/references/design-isms.md +194 -0
  88. package/skills/ima2-uiux/references/design-read-example.md +33 -0
  89. package/skills/ima2-uiux/references/design-system-bootstrap.md +133 -0
  90. package/skills/ima2-uiux/references/favicon-logo.md +355 -0
  91. package/skills/ima2-uiux/references/form-patterns.md +118 -0
  92. package/skills/ima2-uiux/references/intent-discovery-ladder.md +86 -0
  93. package/skills/ima2-uiux/references/korean-design-vocabulary.md +52 -0
  94. package/skills/ima2-uiux/references/layout-macrostructures.md +54 -0
  95. package/skills/ima2-uiux/references/logo-trust-sections.md +96 -0
  96. package/skills/ima2-uiux/references/mobile-native-ux.md +207 -0
  97. package/skills/ima2-uiux/references/product-personalities.md +118 -0
  98. package/skills/ima2-uiux/references/responsive-nav.md +66 -0
  99. package/skills/ima2-uiux/references/typography-line-breaks.md +193 -0
  100. package/skills/ima2-uiux/references/ux-preflight.md +65 -0
  101. package/skills/ima2-uiux/references/ux-states.md +197 -0
  102. package/skills/ima2-uiux/references/visual-hierarchy.md +115 -0
  103. package/ui/dist/.vite/manifest.json +13 -13
  104. package/ui/dist/assets/AgentWorkspace-CtYt4SF5.js +3 -0
  105. package/ui/dist/assets/{CardNewsWorkspace-Cdxn1ohU.js → CardNewsWorkspace-DN5cVqG5.js} +1 -1
  106. package/ui/dist/assets/GenerationRequestLogPanel-DnmUQdKR.js +1 -0
  107. package/ui/dist/assets/{NodeCanvas-C67sLboA.js → NodeCanvas-CxpfIBI0.js} +1 -1
  108. package/ui/dist/assets/PromptBuilderPanel-C2R3ObtR.js +2 -0
  109. package/ui/dist/assets/{PromptImportDialog-DeQXsEEv.js → PromptImportDialog-BIxz_yEx.js} +2 -2
  110. package/ui/dist/assets/PromptImportDiscoverySection-BQTlPMME.js +1 -0
  111. package/ui/dist/assets/PromptImportFolderSection-Ds_Th9O3.js +1 -0
  112. package/ui/dist/assets/{PromptLibraryPanel-Db3xEPM_.js → PromptLibraryPanel-Rs4l45pV.js} +2 -2
  113. package/ui/dist/assets/{SettingsWorkspace-BDk_1W-V.js → SettingsWorkspace-p1AZ6uT9.js} +1 -1
  114. package/ui/dist/assets/index-0-_vgFGs.js +4 -0
  115. package/ui/dist/assets/index-Dm3pFxV4.js +23 -0
  116. package/ui/dist/assets/index-J8yDF3Ch.css +1 -0
  117. package/ui/dist/index.html +2 -2
  118. package/ui/dist/assets/AgentWorkspace-DAg_7zpY.js +0 -3
  119. package/ui/dist/assets/GenerationRequestLogPanel-C_qvEUi2.js +0 -1
  120. package/ui/dist/assets/PromptBuilderPanel-DjvVdAie.js +0 -2
  121. package/ui/dist/assets/PromptImportDiscoverySection-CrwyUKYI.js +0 -1
  122. package/ui/dist/assets/PromptImportFolderSection-CToGMqYE.js +0 -1
  123. package/ui/dist/assets/index-2oG6in1i.css +0 -1
  124. package/ui/dist/assets/index-CoxMOXAU.js +0 -23
  125. package/ui/dist/assets/index-p8egnGHk.js +0 -4
@@ -0,0 +1,264 @@
1
+ # React Stack — Development Rules
2
+
3
+ Rules specific to React projects. Read `core/aesthetics.md`, `core/anti-slop.md`, and `core/visual-verification.md` first.
4
+
5
+ ---
6
+
7
+ ## Domain Routing
8
+
9
+ Before choosing component libraries, read the core references that match the surface:
10
+
11
+ - Korean-first UI → `korea-2026.md`, `ux-writing-ko.md`
12
+ - Tool/dashboard → `product-density.md`
13
+ - Visual/product surface → `asset-requirements.md`
14
+ - Soft 3D/mascot/miniature visuals → `soft-3d-asset-gates.md`
15
+ - Substantial UI change → `visual-verification.md`
16
+
17
+ ## Behavior-First Components
18
+
19
+ Prefer proven behavior primitives for complex interactive components:
20
+
21
+ - Radix / Headless UI for dialog, popover, menu, tabs, combobox-like behavior
22
+ - The project dropdown design layer (`references/core/dropdown-layer.md`
23
+ FE-DROPDOWN-LAYER-01) supplies the SKIN over these primitives; the skin never
24
+ replaces the primitive
25
+ - shadcn/ui as source code scaffolding, not as a final visual design
26
+ - Existing repo components before adding a new dependency
27
+
28
+ Customize tokens, radius, shadows, density, and typography. Do not ship default shadcn visuals.
29
+
30
+ ## Korean Mobile Patterns
31
+
32
+ React apps targeting Korean mobile flows should support:
33
+
34
+ - bottom sheets for lightweight choices
35
+ - full-screen funnels for complex steps
36
+ - sticky bottom action bars
37
+ - snackbar/toast for reversible confirmations
38
+ - safe-area insets
39
+ - `100dvh` instead of `100vh`
40
+ - long Korean label stress tests
41
+
42
+ ## AI Tool States
43
+
44
+ AI features must expose state clearly:
45
+
46
+ - pending / queued
47
+ - streaming or partial result
48
+ - cancel
49
+ - retry
50
+ - undo or revert
51
+ - source/provenance when applicable
52
+ - permission boundary before sensitive actions
53
+ - rate limit or failure recovery
54
+
55
+ Do not hide AI uncertainty behind decorative gradients.
56
+
57
+ ## Architecture
58
+
59
+ ### Server Components When Supported By The Framework
60
+ Use Server Components only in Next App Router or another RSC-enabled framework. In Vite, SPA-only React, React Native Web, or client-only embeds, do not introduce RSC assumptions or `'use client'` boundaries.
61
+
62
+ When the framework supports RSC, default non-interactive route content to Server Components. Add `'use client'` ONLY when you need:
63
+ - Event handlers (`onClick`, `onChange`)
64
+ - State (`useState`, `useReducer`)
65
+ - Effects (`useEffect`)
66
+ - Browser APIs (`window`, `document`)
67
+
68
+ ```tsx
69
+ // Server Component (default) — no 'use client'
70
+ async function ProductPage({ params }) {
71
+ const product = await getProduct(params.id);
72
+ return (
73
+ <div>
74
+ <h1>{product.name}</h1>
75
+ <AddToCartButton productId={product.id} />
76
+ </div>
77
+ );
78
+ }
79
+
80
+ // Client Component — only what MUST be interactive
81
+ 'use client';
82
+ function AddToCartButton({ productId }) {
83
+ const [adding, setAdding] = useState(false);
84
+ return <button onClick={() => addToCart(productId)}>Add</button>;
85
+ }
86
+ ```
87
+
88
+ ### RSC Safety Rules
89
+ - Global state ONLY in Client Components
90
+ - In Next.js, wrap providers in a `'use client'` wrapper component
91
+ - If motion/interactivity needed, extract the interactive part as an **isolated leaf** Client Component
92
+
93
+ ### Interactivity Isolation
94
+ Any component using `useMotionValue`, `useTransform`, or perpetual animations MUST be extracted as a dedicated Client Component in RSC-enabled frameworks. Server Components render static layouts only.
95
+
96
+ ---
97
+
98
+ ## State Management
99
+
100
+ | Need | Solution |
101
+ | ------------------- | ------------------------------------------------------- |
102
+ | Local UI state | `useState` / `useReducer` |
103
+ | Form state | React Hook Form + Zod validation |
104
+ | Server-fetched data | TanStack Query (`@tanstack/react-query`) |
105
+ | Global shared state | Zustand (minimal, flat store) |
106
+ | Deep prop drilling | React Context (for dependency injection, NOT data flow) |
107
+
108
+ **Anti-patterns**:
109
+ - Don't use Context for frequently changing data (causes subtree re-renders)
110
+ - Don't reach for global state when local state suffices
111
+ - Don't use `useEffect` for data fetching — use TanStack Query or Server Components
112
+
113
+ ---
114
+
115
+ ## Component Patterns
116
+
117
+ ### Compound Components
118
+ ```tsx
119
+ const Tabs = ({ children }) => {
120
+ const [active, setActive] = useState(0);
121
+ return (
122
+ <TabsContext.Provider value={{ active, setActive }}>
123
+ {children}
124
+ </TabsContext.Provider>
125
+ );
126
+ };
127
+ Tabs.List = TabList;
128
+ Tabs.Panel = TabPanel;
129
+ ```
130
+
131
+ ### Custom Hooks (extract reusable logic)
132
+ ```tsx
133
+ function useDebounce<T>(value: T, delay = 500): T {
134
+ const [debounced, setDebounced] = useState(value);
135
+ useEffect(() => {
136
+ const timer = setTimeout(() => setDebounced(value), delay);
137
+ return () => clearTimeout(timer);
138
+ }, [value, delay]);
139
+ return debounced;
140
+ }
141
+ ```
142
+
143
+ ### Generic List Component
144
+ ```tsx
145
+ interface ListProps<T> {
146
+ items: T[];
147
+ renderItem: (item: T) => React.ReactNode;
148
+ }
149
+ function List<T>({ items, renderItem }: ListProps<T>) {
150
+ return <ul>{items.map(renderItem)}</ul>;
151
+ }
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Styling
157
+
158
+ ### Tailwind CSS
159
+ - Check `package.json` for Tailwind version. Do NOT mix v3/v4 syntax.
160
+ - **T4 CONFIG GUARD**: For v4, do NOT use `tailwindcss` plugin in `postcss.config.js`. Use `@tailwindcss/postcss` or Vite plugin.
161
+ - Use `cn()` utility for conditional classes:
162
+ ```tsx
163
+ import { cn } from '@/lib/utils';
164
+ <button className={cn(
165
+ 'px-4 py-2 rounded',
166
+ variant === 'primary' && 'bg-emerald-500 text-white',
167
+ disabled && 'opacity-50 cursor-not-allowed'
168
+ )} />
169
+ ```
170
+
171
+ ### shadcn/ui
172
+ - MUST customize defaults — never ship generic appearance
173
+ - Override `--radius`, color palette, shadow depth
174
+ - All components should match project's aesthetic direction
175
+
176
+ ### CSS Variables for Design Tokens
177
+ ```css
178
+ :root {
179
+ --color-primary: oklch(0.7 0.15 160);
180
+ --color-surface: oklch(0.98 0 0);
181
+ --radius-default: 0.75rem;
182
+ --shadow-card: 0 20px 40px -15px rgba(0,0,0,0.05);
183
+ }
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Dependency Verification [MANDATORY]
189
+
190
+ Before importing ANY 3rd party library:
191
+ 1. Check `package.json`
192
+ 2. If missing, output `npm install <package>` BEFORE providing code
193
+ 3. **Never assume** a library exists
194
+
195
+ ---
196
+
197
+ ## Icons
198
+
199
+ Use EXACTLY `@phosphor-icons/react` or `@radix-ui/react-icons` as import paths.
200
+ Standardize `strokeWidth` globally (e.g., exclusively `1.5` or `2.0`).
201
+ **NEVER** use emoji — see `anti-slop.md`.
202
+
203
+ ---
204
+
205
+ ## Performance
206
+
207
+ ### Bundle Optimization
208
+ | Heavy Package | Size | Alternative |
209
+ | ------------- | ----- | ------------------------------ |
210
+ | moment | 290KB | date-fns (12KB) or dayjs (2KB) |
211
+ | lodash | 71KB | lodash-es with tree-shaking |
212
+ | axios | 14KB | Native fetch or ky (3KB) |
213
+ | @mui/material | Large | shadcn/ui or Radix UI |
214
+
215
+ ### Rendering
216
+ - Parallel fetch: `Promise.all([getUser(), getStats()])`
217
+ - Streaming: `<Suspense fallback={<Skeleton />}>`
218
+ - Avoid waterfall: never fetch sequentially in nested components
219
+ - `React.memo` for expensive pure components
220
+ - `useMemo` / `useCallback` only when measured, not preemptively
221
+
222
+ ### Image Optimization
223
+ ```tsx
224
+ // Above fold — load immediately
225
+ <Image src="/hero.jpg" alt="Hero" width={1200} height={600} priority />
226
+
227
+ // Responsive fill
228
+ <div className="relative aspect-video">
229
+ <Image src="/product.jpg" alt="Product" fill
230
+ sizes="(max-width: 768px) 100vw, 50vw"
231
+ className="object-cover" />
232
+ </div>
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Testing
238
+
239
+ ```tsx
240
+ import { render, screen } from '@testing-library/react';
241
+ import userEvent from '@testing-library/user-event';
242
+
243
+ test('button triggers action', async () => {
244
+ const onClick = vi.fn();
245
+ render(<Button onClick={onClick}>Click</Button>);
246
+ await userEvent.click(screen.getByRole('button'));
247
+ expect(onClick).toHaveBeenCalledTimes(1);
248
+ });
249
+
250
+ test('dialog is accessible', () => {
251
+ render(<Dialog open title="Confirm" />);
252
+ expect(screen.getByRole('dialog')).toHaveAttribute('aria-labelledby');
253
+ });
254
+ ```
255
+
256
+ ---
257
+
258
+ ## Responsiveness
259
+
260
+ - Standardize breakpoints: `sm`, `md`, `lg`, `xl`
261
+ - Contain layouts: `max-w-[1400px] mx-auto` or `max-w-7xl`
262
+ - **NEVER** `h-screen` for full-height. ALWAYS `min-h-[100dvh]`
263
+ - **NEVER** `w-[calc(33%-1rem)]`. ALWAYS CSS Grid
264
+ - DESIGN_VARIANCE levels 4-10: aggressive single-column fallback on `< 768px`
@@ -0,0 +1,235 @@
1
+ # Svelte 5 / SvelteKit 2 Stack
2
+
3
+ Last reviewed: 2026-06-16
4
+ Applies to: Svelte 5.x (Runes), SvelteKit 2.x
5
+ When to read: Building or modifying Svelte/SvelteKit projects
6
+ Canonical owner: dev-frontend
7
+
8
+ Read `core/aesthetics.md` + `core/anti-slop.md` first.
9
+
10
+ ## 1. Runes (Svelte 5)
11
+
12
+ Svelte 5 replaces stores and reactive declarations with **Runes** — explicit reactivity primitives:
13
+
14
+ | Rune | Replaces | Purpose |
15
+ |------|----------|---------|
16
+ | `$state()` | `let x = 0` (reactive) | Declare reactive state |
17
+ | `$derived()` | `$: doubled = x * 2` | Computed value from state |
18
+ | `$effect()` | `$: { sideEffect() }` | Side effect on state change |
19
+ | `$props()` | `export let prop` | Declare component props |
20
+ | `$bindable()` | `export let value` (two-way) | Two-way bindable prop |
21
+ | `$inspect()` | `console.log` debugging | Dev-only reactive logging (stripped in prod) |
22
+
23
+ ```svelte
24
+ <script>
25
+ let { title, onSave } = $props();
26
+ let count = $state(0);
27
+ let doubled = $derived(count * 2);
28
+
29
+ $effect(() => {
30
+ console.log(`count changed to ${count}`);
31
+ return () => { /* cleanup */ };
32
+ });
33
+ </script>
34
+
35
+ <button onclick={() => count++}>
36
+ {title}: {count} (doubled: {doubled})
37
+ </button>
38
+ ```
39
+
40
+ Rules:
41
+ - Use `$state()` for all mutable reactive values — bare `let` is no longer reactive in Svelte 5.
42
+ - Prefer `$derived()` over `$effect()` for computed values — effects are for side effects only.
43
+ - `$effect()` runs after DOM update. Use `$effect.pre()` only when you need pre-DOM-update timing.
44
+ - Use `$inspect()` for debugging, never `console.log` inside `$effect()` — `$inspect` is stripped from production builds.
45
+ - Destructure `$props()` at the top of `<script>` — do not access `$$props` or `$$restProps` (Svelte 4 patterns).
46
+
47
+ ## 2. SvelteKit 2
48
+
49
+ ### Routing & Data Loading
50
+
51
+ ```
52
+ src/routes/
53
+ ├── +layout.svelte # root layout
54
+ ├── +layout.server.ts # root layout data (runs on server)
55
+ ├── +page.svelte # home page
56
+ ├── +page.server.ts # home page data (runs on server)
57
+ ├── blog/
58
+ │ ├── +page.svelte # blog list
59
+ │ ├── +page.server.ts # blog list data
60
+ │ └── [slug]/
61
+ │ ├── +page.svelte # blog post
62
+ │ └── +page.server.ts # blog post data
63
+ └── api/
64
+ └── posts/
65
+ └── +server.ts # API endpoint
66
+ ```
67
+
68
+ | File | Runs On | Purpose |
69
+ |------|---------|---------|
70
+ | `+page.server.ts` → `load()` | Server only | Fetch data, access DB, read secrets |
71
+ | `+page.ts` → `load()` | Server + client | Universal data loading (no secrets) |
72
+ | `+page.svelte` | Client (hydrated) | Render UI with loaded data |
73
+ | `+server.ts` | Server only | API endpoints (GET, POST, PUT, DELETE) |
74
+ | `+layout.server.ts` | Server only | Shared layout data (auth, user session) |
75
+
76
+ ### Form Actions
77
+
78
+ ```typescript
79
+ // +page.server.ts
80
+ export const actions = {
81
+ create: async ({ request, locals }) => {
82
+ const data = await request.formData();
83
+ const title = data.get('title');
84
+
85
+ if (!title) {
86
+ return fail(400, { title, missing: true });
87
+ }
88
+
89
+ await db.posts.create({ data: { title, author: locals.user.id } });
90
+ redirect(303, '/blog');
91
+ }
92
+ };
93
+ ```
94
+
95
+ ```svelte
96
+ <!-- +page.svelte -->
97
+ <script>
98
+ import { enhance } from '$app/forms';
99
+ let { form } = $props();
100
+ </script>
101
+
102
+ <form method="POST" action="?/create" use:enhance>
103
+ <input name="title" value={form?.title ?? ''} />
104
+ {#if form?.missing}<p class="error">Title required</p>{/if}
105
+ <button>Create</button>
106
+ </form>
107
+ ```
108
+
109
+ Rules:
110
+ - Always use `+page.server.ts` for data that requires secrets, DB access, or auth checks.
111
+ - Use form actions for mutations — progressive enhancement works without JavaScript.
112
+ - Validate server-side in form actions — client validation is UX, not security.
113
+ - Use `redirect()` and `error()` from `@sveltejs/kit`, not manual response construction.
114
+ - Use `$app/stores` sparingly in Svelte 5 — prefer `$props()` data flow from `load()`.
115
+
116
+ ### SvelteKit Adapters
117
+
118
+ | Adapter | Target | Install |
119
+ |---------|--------|---------|
120
+ | `@sveltejs/adapter-auto` | Auto-detect (Vercel, Netlify, Cloudflare) | Default — included in new projects |
121
+ | `@sveltejs/adapter-node` | Node.js server (Docker, VPS) | `npm i -D @sveltejs/adapter-node` |
122
+ | `@sveltejs/adapter-static` | Static site (GitHub Pages, S3) | `npm i -D @sveltejs/adapter-static` |
123
+ | `@sveltejs/adapter-vercel` | Vercel (edge/serverless) | `npm i -D @sveltejs/adapter-vercel` |
124
+ | `@sveltejs/adapter-cloudflare` | Cloudflare Workers/Pages | `npm i -D @sveltejs/adapter-cloudflare` |
125
+
126
+ ### Performance Characteristics
127
+
128
+ | Metric | Svelte 5 | React 19 | Vue 3.5 |
129
+ |--------|----------|----------|---------|
130
+ | Bundle size (hello world) | ~2 KB | ~45 KB | ~30 KB |
131
+ | Reactivity model | Compile-time (runes) | Runtime (fiber + hooks) | Runtime (proxy) |
132
+ | Virtual DOM | No — direct DOM updates | Yes | Yes |
133
+ | SSR streaming | SvelteKit `+page.server.ts` | React Server Components | Nuxt `useAsyncData` |
134
+ | Built-in transitions | Yes (`svelte/transition`) | No (need library) | Yes (`<Transition>`) |
135
+ | Scoped CSS | Default (`<style>`) | No (need CSS modules/Tailwind) | Default (`<style scoped>`) |
136
+
137
+ ## 3. Component Patterns
138
+
139
+ ### Snippets (Svelte 5 — replaces slots)
140
+
141
+ ```svelte
142
+ <!-- Parent -->
143
+ <Card>
144
+ {#snippet header()}
145
+ <h2>Title</h2>
146
+ {/snippet}
147
+ {#snippet footer()}
148
+ <button>Action</button>
149
+ {/snippet}
150
+ <p>Default content</p>
151
+ </Card>
152
+
153
+ <!-- Card.svelte -->
154
+ <script>
155
+ let { header, footer, children } = $props();
156
+ </script>
157
+
158
+ <div class="card">
159
+ {#if header}{@render header()}{/if}
160
+ {@render children()}
161
+ {#if footer}{@render footer()}{/if}
162
+ </div>
163
+ ```
164
+
165
+ ### Transitions & Animations
166
+
167
+ ```svelte
168
+ <script>
169
+ import { fly, fade } from 'svelte/transition';
170
+ import { flip } from 'svelte/animate';
171
+
172
+ let items = $state([]);
173
+ </script>
174
+
175
+ {#each items as item (item.id)}
176
+ <div
177
+ animate:flip={{ duration: 300 }}
178
+ in:fly={{ y: 20, duration: 200 }}
179
+ out:fade={{ duration: 150 }}
180
+ >
181
+ {item.name}
182
+ </div>
183
+ {/each}
184
+ ```
185
+
186
+ Rules:
187
+ - Use Snippets instead of slots — slots are deprecated in Svelte 5.
188
+ - Use `{@render}` for snippet rendering, not `<svelte:component>`.
189
+ - Scoped `<style>` is default — use `:global()` only when intentionally escaping scope.
190
+ - Prefer CSS transitions for simple effects; use Svelte transitions for enter/exit/list animations.
191
+ - Always provide `(key)` in `{#each}` blocks for stable identity.
192
+
193
+ ## 4. Migration from Svelte 4
194
+
195
+ | Svelte 4 | Svelte 5 | Migration |
196
+ |----------|----------|-----------|
197
+ | `export let prop` | `let { prop } = $props()` | Destructure from `$props()` |
198
+ | `$: derived = x * 2` | `let derived = $derived(x * 2)` | Wrap in `$derived()` |
199
+ | `$: { sideEffect() }` | `$effect(() => { sideEffect() })` | Wrap in `$effect()` |
200
+ | `<slot />` | `{@render children()}` | Replace slots with snippets |
201
+ | `<slot name="x" />` | `{@render x()}` | Named slots → named snippets |
202
+ | `$$props` / `$$restProps` | `let { ...rest } = $props()` | Destructure with rest |
203
+ | Writable stores | `$state()` in `.svelte.ts` | Move to Rune-based state |
204
+ | `createEventDispatcher()` | Callback props | Pass functions via `$props()` |
205
+
206
+ ```bash
207
+ # Automated migration (partial — review output manually)
208
+ npx svelte-migrate svelte-5
209
+ ```
210
+
211
+ Rules:
212
+ - Migrate one component at a time — Svelte 5 components can coexist with Svelte 4 in the same project.
213
+ - Test each migrated component individually before proceeding.
214
+ - Stores in `.js`/`.ts` files still work — migrate to `.svelte.ts` Rune-based state when touching the file.
215
+ - `createEventDispatcher` → callback props is the biggest behavioral change; verify all event consumers.
216
+
217
+ ## 5. Anti-Patterns
218
+
219
+ | Banned | Symptom | Fix |
220
+ |--------|---------|-----|
221
+ | `$effect()` for derived values | Unnecessary re-runs, stale value bugs | Use `$derived()` instead |
222
+ | Missing `(key)` in `{#each}` | Animation glitches, wrong element updates | Always provide a stable key |
223
+ | `$$props` in Svelte 5 | Deprecated, loses type safety | Destructure from `$props()` |
224
+ | Bare `let` expecting reactivity | Value does not update in template | Use `$state()` for reactive values |
225
+ | `on:click` syntax in Svelte 5 | Deprecated event directive | Use `onclick` attribute |
226
+
227
+ ## Pre-flight
228
+
229
+ - [ ] All reactive state uses `$state()`, not bare `let`
230
+ - [ ] Computed values use `$derived()`, not `$effect()`
231
+ - [ ] Components use `$props()` destructuring, not `export let`
232
+ - [ ] `{#each}` blocks have stable keys
233
+ - [ ] Server-only data in `+page.server.ts`, not `+page.ts`
234
+ - [ ] Form actions validate server-side
235
+ - [ ] Slots migrated to Snippets (`{@render}`) in new/updated components