svelte
Svelte 5とSvelteKit 2のエキスパートとして、ラン、スニペット、ストアなどを活用し、仮想DOMなしで最小限のJavaScriptにコンパイルしてWebアプリ開発を支援するSkill。
📜 元の英語説明(参考)
You are an expert in Svelte 5 and SvelteKit 2. You help developers build web applications using runes ($state, $derived, $effect, $props, $bindable, $inspect), snippets, stores, transitions, and actions — compiling to minimal vanilla JavaScript with no virtual DOM. Use when building Svelte apps, migrating from Svelte 4, or working with SvelteKit.
🇯🇵 日本人クリエイター向け解説
Svelte 5とSvelteKit 2のエキスパートとして、ラン、スニペット、ストアなどを活用し、仮想DOMなしで最小限のJavaScriptにコンパイルしてWebアプリ開発を支援するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o svelte.zip https://jpskill.com/download/15434.zip && unzip -o svelte.zip && rm svelte.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15434.zip -OutFile "$d\svelte.zip"; Expand-Archive "$d\svelte.zip" -DestinationPath $d -Force; ri "$d\svelte.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
svelte.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
svelteフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Svelte — コンパイル時リアクティブ UI フレームワーク
概要
Svelte は、ランタイムからコンパイル時に処理を移行し、仮想 DOM を持たない最小限のプレーンな JavaScript を生成します。Svelte 5 では、$: 宣言やストアに代わる、明示的なリアクティビティプリミティブである runes が導入されました。SvelteKit 2 は、SSR、ルーティング、およびデプロイメントアダプターを提供します。
手順
Runes リファレンス
$state — リアクティブな状態 (デフォルトではディープ):
<script lang="ts">
let count = $state(0);
let user = $state({ name: "Alice", age: 30 });
user.age++; // ディープリアクティビティ — 更新をトリガー
</script>
$state.raw — シャローリアクティブ (トリガーするには再代入が必要):
<script>
let items = $state.raw([1, 2, 3]);
items = [...items, 4]; // 再代入が必要
</script>
$state.snapshot — プレーンな非リアクティブコピー:
<script>
let form = $state({ name: "", email: "" });
const data = $state.snapshot(form); // API 呼び出し用のプレーンなオブジェクト
</script>
$derived および $derived.by — 算出値:
<script>
let price = $state(100);
let quantity = $state(3);
let total = $derived(price * quantity);
let summary = $derived.by(() => {
const t = items.reduce((sum, i) => sum + i.price, 0);
return { total: t, count: items.length, avg: t / items.length };
});
</script>
$effect — クリーンアップ付きの副作用:
<script>
let query = $state("");
$effect(() => {
if (!query) return;
const controller = new AbortController();
fetch(`/api/search?q=${query}`, { signal: controller.signal })
.then(r => r.json()).then(data => { results = data; });
return () => controller.abort();
});
</script>
$props — コンポーネントの props:
<script>
let { label, variant = "primary", onclick, class: className = "", ...rest } = $props();
</script>
<button class="btn btn-{variant} {className}" {onclick} {...rest}>{label}</button>
$bindable — 双方向バインディング:
<!-- Input.svelte -->
<script>
let { value = $bindable(""), placeholder = "" } = $props();
</script>
<input bind:value {placeholder} />
$inspect — リアクティブな値のデバッグ (開発時のみ):
<script>
$inspect(count, doubled);
$inspect(count).with((type, value) => console.log(`[${type}]`, value));
</script>
スニペット (スロットの置き換え)
Svelte 5 では、スロットが型付きの再利用可能なマークアップフラグメントに置き換えられました。
<!-- List.svelte -->
<script>
let { items, row, children } = $props();
</script>
<ul>
{#each items as item}
<li>{@render row(item)}</li>
{/each}
</ul>
{@render children?.()}
<!-- Parent.svelte -->
<List {items}>
{#snippet row(item)}
<strong>{item.name}</strong> — {item.description}
{/snippet}
</List>
ストア (共有状態)
// stores/cart.ts — 書き込み可能なストア (Svelte 4 スタイル、まだ動作します)
import { writable, derived } from "svelte/store";
export const cart = writable<CartItem[]>([]);
export const cartTotal = derived(cart, ($cart) =>
$cart.reduce((sum, item) => sum + item.price * item.quantity, 0)
);
Svelte 5 の代替 — .svelte.ts モジュールでの $state:
// state/counter.svelte.ts
let count = $state(0);
let doubled = $derived(count * 2);
export function getCounter() {
return {
get count() { return count; },
get doubled() { return doubled; },
increment() { count++; },
};
}
トランジション
<script>
import { fade, fly, slide } from "svelte/transition";
import { flip } from "svelte/animate";
let items = $state(["Apple", "Banana"]);
</script>
{#each items as item (item)}
<div animate:flip={{ duration: 300 }} transition:fade>{item}</div>
{/each}
Svelte 4 からの移行
| Svelte 4 | Svelte 5 |
|---|---|
let count = 0 |
let count = $state(0) |
$: doubled = count * 2 |
let doubled = $derived(count * 2) |
$: { sideEffect() } |
$effect(() => { sideEffect() }) |
export let prop |
let { prop } = $props() |
<slot /> |
{@render children()} |
<slot name="header" /> |
{@render header?.()} |
| Svelte stores | .svelte.ts ファイルでの $state |
SvelteKit 2
<!-- +page.svelte -->
<script>
let { data } = $props(); // +page.ts の load 関数から
</script>
<h1>{data.title}</h1>
npx sv create my-app # SvelteKit プロジェクト
npm create vite@latest -- --template svelte-ts # スタンドアロン Svelte
例
例 1: ストアを使用したショッピングカート
<!-- CartSummary.svelte -->
<script lang="ts">
import { cart, cartTotal, removeFromCart } from "$lib/stores/cart";
</script>
<div class="cart">
{#each $cart as item (item.id)}
<div>{item.name} x {item.quantity} — ${(item.price * item.quantity).toFixed(2)}
<button onclick={() => removeFromCart(item.id)}>Remove</button>
</div>
{/each}
<p>Total: ${$cartTotal.toFixed(2)}</p>
</div>
例 2: $effect を使用した非同期データフェッチ
<script>
let userId = $state(1);
let user = $state(null);
let loading = $state(false);
$effect(() => {
loading = true;
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => { user = data; loading = false; });
});
</script>
{#if loading}<p>Loading...</p>
{:else if user}<p>{user.name}</p>{/if}
ガイドライン
- 状態のための Runes — Svelte 5 では
$state()、$derived()、$effect()を使用します。Svelte 4 の$:構文よりもクリーンです。 - スコープ付きスタイル —
<style>の CSS はコンポーネントスコープです。CSS モジュールは不要です。 - ストア vs runes — 新しいコードには
.svelte.tsで$stateを使用します。書き込み可能/派生ストアはまだ動作します。 - 組み込みのトランジション —
transition:fade、transition:flyを使用します。アニメーションライブラリは不要です。 - 小さなバンドル — Svelte はコンパイルされます。一般的なアプリのサイズは 5〜10KB で、React の 40KB 以上と比較して小さくなります。
- フルスタックのための SvelteKit — SSR、ルーティング、API エンドポイント、デプロイメントアダプター
- TypeScript — 型安全なコンポーネントには
<script lang="ts">を使用します。 - DOM のためのアクション — `use:a
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Svelte — Compile-Time Reactive UI Framework
Overview
Svelte shifts work from runtime to compile time, producing minimal vanilla JavaScript with no virtual DOM. Svelte 5 introduces runes — explicit reactivity primitives that replace $: declarations and stores. SvelteKit 2 provides SSR, routing, and deployment adapters.
Instructions
Runes Reference
$state — reactive state (deep by default):
<script lang="ts">
let count = $state(0);
let user = $state({ name: "Alice", age: 30 });
user.age++; // deep reactivity — triggers updates
</script>
$state.raw — shallow reactive (must reassign to trigger):
<script>
let items = $state.raw([1, 2, 3]);
items = [...items, 4]; // must reassign
</script>
$state.snapshot — plain non-reactive copy:
<script>
let form = $state({ name: "", email: "" });
const data = $state.snapshot(form); // plain object for API calls
</script>
$derived and $derived.by — computed values:
<script>
let price = $state(100);
let quantity = $state(3);
let total = $derived(price * quantity);
let summary = $derived.by(() => {
const t = items.reduce((sum, i) => sum + i.price, 0);
return { total: t, count: items.length, avg: t / items.length };
});
</script>
$effect — side effects with cleanup:
<script>
let query = $state("");
$effect(() => {
if (!query) return;
const controller = new AbortController();
fetch(`/api/search?q=${query}`, { signal: controller.signal })
.then(r => r.json()).then(data => { results = data; });
return () => controller.abort();
});
</script>
$props — component props:
<script>
let { label, variant = "primary", onclick, class: className = "", ...rest } = $props();
</script>
<button class="btn btn-{variant} {className}" {onclick} {...rest}>{label}</button>
$bindable — two-way binding:
<!-- Input.svelte -->
<script>
let { value = $bindable(""), placeholder = "" } = $props();
</script>
<input bind:value {placeholder} />
$inspect — debug reactive values (dev only):
<script>
$inspect(count, doubled);
$inspect(count).with((type, value) => console.log(`[${type}]`, value));
</script>
Snippets (Replacing Slots)
Svelte 5 replaces slots with typed, reusable markup fragments:
<!-- List.svelte -->
<script>
let { items, row, children } = $props();
</script>
<ul>
{#each items as item}
<li>{@render row(item)}</li>
{/each}
</ul>
{@render children?.()}
<!-- Parent.svelte -->
<List {items}>
{#snippet row(item)}
<strong>{item.name}</strong> — {item.description}
{/snippet}
</List>
Stores (Shared State)
// stores/cart.ts — Writable store (Svelte 4 style, still works)
import { writable, derived } from "svelte/store";
export const cart = writable<CartItem[]>([]);
export const cartTotal = derived(cart, ($cart) =>
$cart.reduce((sum, item) => sum + item.price * item.quantity, 0)
);
Svelte 5 alternative — $state in .svelte.ts modules:
// state/counter.svelte.ts
let count = $state(0);
let doubled = $derived(count * 2);
export function getCounter() {
return {
get count() { return count; },
get doubled() { return doubled; },
increment() { count++; },
};
}
Transitions
<script>
import { fade, fly, slide } from "svelte/transition";
import { flip } from "svelte/animate";
let items = $state(["Apple", "Banana"]);
</script>
{#each items as item (item)}
<div animate:flip={{ duration: 300 }} transition:fade>{item}</div>
{/each}
Migration from Svelte 4
| Svelte 4 | Svelte 5 |
|---|---|
let count = 0 |
let count = $state(0) |
$: doubled = count * 2 |
let doubled = $derived(count * 2) |
$: { sideEffect() } |
$effect(() => { sideEffect() }) |
export let prop |
let { prop } = $props() |
<slot /> |
{@render children()} |
<slot name="header" /> |
{@render header?.()} |
| Svelte stores | $state in .svelte.ts files |
SvelteKit 2
<!-- +page.svelte -->
<script>
let { data } = $props(); // from +page.ts load function
</script>
<h1>{data.title}</h1>
npx sv create my-app # SvelteKit project
npm create vite@latest -- --template svelte-ts # standalone Svelte
Examples
Example 1: Shopping cart with stores
<!-- CartSummary.svelte -->
<script lang="ts">
import { cart, cartTotal, removeFromCart } from "$lib/stores/cart";
</script>
<div class="cart">
{#each $cart as item (item.id)}
<div>{item.name} x {item.quantity} — ${(item.price * item.quantity).toFixed(2)}
<button onclick={() => removeFromCart(item.id)}>Remove</button>
</div>
{/each}
<p>Total: ${$cartTotal.toFixed(2)}</p>
</div>
Example 2: Async data fetching with $effect
<script>
let userId = $state(1);
let user = $state(null);
let loading = $state(false);
$effect(() => {
loading = true;
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => { user = data; loading = false; });
});
</script>
{#if loading}<p>Loading...</p>
{:else if user}<p>{user.name}</p>{/if}
Guidelines
- Runes for state — Use
$state(),$derived(),$effect()in Svelte 5; cleaner than Svelte 4's$:syntax - Scoped styles — CSS in
<style>is component-scoped; no CSS modules needed - Stores vs runes — Use
$statein.svelte.tsfor new code; writable/derived stores still work - Transitions built-in — Use
transition:fade,transition:fly; no animation library needed - Small bundles — Svelte compiles away; typical app ships 5-10KB vs 40KB+ for React
- SvelteKit for full-stack — SSR, routing, API endpoints, deployment adapters
- TypeScript — Use
<script lang="ts">for type-safe components - Actions for DOM — Use
use:actionfor reusable DOM behavior (click-outside, tooltip)