Skip to content
cccskills
FreePublished on GitHub

svelte-sveltekit-expert

Expert guide for Svelte 5 (Runes) and SvelteKit 2+ — fine-grained reactivity, snippets, server-first architecture, form actions, and SSR/SSG / Panduan ahli Svelte 5 (Runes) dan SvelteKit 2+ — reaktivitas fine-grained, snippets, arsitektur server-first, form actions, dan SSR/SSG.

The English summary is being prepared. Showing the original description.

See how to install

Files included (1)

  • SKILL.md15.7 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Svelte 5 & SvelteKit 2 Expert (Runes Standard 2026)

English | Bahasa Indonesia


<a name="english"></a>

English

Orchestration & Integration

  • Upstream System Design: brainstorming, zero-to-prod-orchestrator (Phase 3 & Phase 4).
  • Styling & Web Standards: modern-web-guidance, tailwind-expert, modern-css-native-expert, design-system-architect.
  • Quality & Performance: performance-web-vitals, e2e-testing-expert, anti-slop, visual-ui-auditor.
  • Backend & APIs: js-backend-expert, database-orm-expert, typescript-expert.

Description

Production-grade guide for building high-performance web applications using Svelte 5 and SvelteKit 2+. Covers the complete Runes reactivity paradigm ($state, $derived, $derived.by, $effect, $props, $bindable), snippet composition replacing legacy slots, progressive enhancement form actions (use:enhance), streaming server promises in +page.server.ts, and shallow routing (pushState) for modal overlays.

Trigger Conditions

  • Scaffolding new applications with Svelte 5 and SvelteKit 2.
  • Refactoring legacy Svelte 3/4 reactive declarations (let x = 0; $: doubled = x * 2;) to Svelte 5 Runes.
  • Composing modular UI components using Svelte 5 Snippets instead of legacy <slot>.
  • Implementing form submissions with atomic server actions and zero-JS progressive enhancement.
  • Streaming large asynchronous datasets to the client without blocking the initial SSR HTML payload.

Core Architectural Patterns

1. Complete Svelte 5 Runes Reference

RunePurposeSvelte 4 Legacy Syntax
$state(val)Deeply reactive state proxylet val = ...
$state.raw(val)Shallow reactive state (ideal for immutable/large payloads)N/A
$derived(expr)Cached reactive derivation$: val = expr
$derived.by(() => {})Complex multi-line derived computation$: { ... }
$effect(() => {})Post-DOM mount & update side-effect with cleanuponMount, afterUpdate, $: { ... }
$effect.pre(() => {})Pre-DOM update effect (e.g. scroll position capture)beforeUpdate
$props()Type-safe destructured component propsexport let prop
$bindable()Explicit two-way prop binding allowanceDirect two-way binding
$inspect(val)Automatic dev-mode deep state inspectorconsole.log(val) in $:

2. Component Composition with Svelte 5 Snippets (No Slots)

In Svelte 5, <slot> is deprecated. Components accept Snippets as typed functions:

<!-- src/lib/components/DataTable.svelte -->
<script lang="ts" generics="T">
  import type { Snippet } from 'svelte';

  interface Props {
    items: T[];
    header: Snippet;
    row: Snippet<[T]>;
    empty?: Snippet;
  }

  let { items, header, row, empty }: Props = $props();
</script>

<div class="overflow-x-auto rounded-xl border border-border bg-card">
  <table class="w-full text-left text-sm">
    <thead class="border-b border-border bg-muted/50 text-xs uppercase font-semibold text-muted-foreground">
      {@render header()}
    </thead>
    <tbody class="divide-y divide-border">
      {#each items as item}
        <tr class="hover:bg-muted/30 transition-colors">
          {@render row(item)}
        </tr>
      {:else}
        {#if empty}
          <tr>
            <td colspan="100%" class="p-8 text-center text-muted-foreground">
              {@render empty()}
            </td>
          </tr>
        {/if}
      {/each}
    </tbody>
  </table>
</div>
<!-- Usage in consumer page -->
<script lang="ts">
  import DataTable from '$lib/components/DataTable.svelte';

  interface User {
    id: string;
    name: string;
    email: string;
    role: string;
  }

  let users = $state<User[]>([
    { id: '1', name: 'Alice Smith', email: 'alice@example.com', role: 'Admin' },
    { id: '2', name: 'Bob Jones', email: 'bob@example.com', role: 'Developer' },
  ]);
</script>

{#snippet tableHeader()}
  <tr>
    <th class="p-3">Name</th>
    <th class="p-3">Email</th>
    <th class="p-3">Role</th>
  </tr>
{/snippet}

{#snippet tableRow(user: User)}
  <td class="p-3 font-medium">{user.name}</td>
  <td class="p-3 text-muted-foreground font-mono">{user.email}</td>
  <td class="p-3"><span class="px-2 py-0.5 rounded text-xs bg-primary/10 text-primary">{user.role}</span></td>
{/snippet}

<DataTable items={users} header={tableHeader} row={tableRow} />

3. Two-Way Binding with $bindable()

<!-- src/lib/components/SearchInput.svelte -->
<script lang="ts">
  interface Props {
    value: string;
    placeholder?: string;
  }

  let { value = $bindable(''), placeholder = 'Search...' }: Props = $props();
</script>

<input
  type="text"
  bind:value
  {placeholder}
  class="px-3 py-2 border rounded-md bg-background text-sm w-full focus:outline-none focus:ring-1 focus:ring-primary"
/>

4. SvelteKit 2 Server Actions with Progressive Enhancement

Atomic server mutation with optimistic state and zero-JS fallback:

// src/routes/tasks/+page.server.ts
import { fail } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import { db } from '$lib/server/db';

export const load: PageServerLoad = async ({ locals }) => {
  // Non-blocking streaming promise: do not await slow telemetry data
  return {
    tasks: await db.tasks.findMany({ orderBy: { createdAt: 'desc' } }),
    streamedMetrics: fetchLiveMetrics(), // Streamed as Promise without blocking HTML
  };
};

export const actions: Actions = {
  createTask: async ({ request }) => {
    const data = await request.formData();
    const title = data.get('title')?.toString().trim();

    if (!title || title.length < 3) {
      return fail(400, { title, error: 'Title must contain at least 3 characters.' });
    }

    const newTask = await db.tasks.create({ data: { title, completed: false } });
    return { success: true, task: newTask };
  },
};

async function fetchLiveMetrics() {
  await new Promise((r) => setTimeout(r, 400));
  return { activeNodes: 12, uptime: '99.99%' };
}
<!-- src/routes/tasks/+page.svelte -->
<script lang="ts">
  import { enhance } from '$app/forms';
  let { data, form } = $props();

  let isSubmitting = $state(false);
  let optimisticTasks = $state([...data.tasks]);

  $effect(() => {
    optimisticTasks = [...data.tasks];
  });
</script>

<div class="max-w-xl mx-auto py-8 space-y-6">
  <h1 class="text-2xl font-bold">Project Tasks</h1>

  <form
    method="POST"
    action="?/createTask"
    use:enhance={({ formData, cancel }) => {
      const title = formData.get('title')?.toString().trim();
      if (!title) {
        cancel();
        return;
      }

      isSubmitting = true;
      // Optimistic update
      optimisticTasks = [{ id: `temp-${Date.now()}`, title, completed: false }, ...optimisticTasks];

      return async ({ update }) => {
        isSubmitting = false;
        await update();
      };
    }}
    class="flex gap-2"
  >
    <input
      name="title"
      type="text"
      placeholder="What needs to be done?"
      required
      class="flex-1 px-3 py-2 border rounded-md bg-background text-sm"
    />
    <button
      type="submit"
      disabled={isSubmitting}
      class="px-4 py-2 bg-primary text-primary-foreground font-medium rounded-md disabled:opacity-50 text-sm"
    >
      {isSubmitting ? 'Saving...' : 'Add Task'}
    </button>
  </form>

  {#if form?.error}
    <p class="text-sm font-semibold text-destructive">{form.error}</p>
  {/if}

  <ul class="divide-y divide-border border rounded-xl bg-card">
    {#each optimisticTasks as task (task.id)}
      <li class="p-3 text-sm flex items-center justify-between">
        <span>{task.title}</span>
        {#if task.id.startsWith('temp-')}
          <span class="text-xs text-muted-foreground font-mono">Syncing...</span>
        {/if}
      </li>
    {/each}
  </ul>

  <!-- Await streamed non-blocking metrics -->
  {#await data.streamedMetrics}
    <div class="p-4 border rounded-lg bg-muted/40 text-xs animate-pulse text-muted-foreground">
      Loading cluster metrics...
    </div>
  {:then metrics}
    <div class="p-4 border rounded-lg bg-card text-xs flex justify-between font-mono">
      <span>Active Nodes: {metrics.activeNodes}</span>
      <span>Uptime: {metrics.uptime}</span>
    </div>
  {/await}
</div>

<a name="bahasa-indonesia"></a>

Bahasa Indonesia

Integrasi Orkestrasi

  • Ideasi & Desain Sistem: brainstorming, zero-to-prod-orchestrator (Fase 3 & Fase 4).
  • Styling & Standar Web: modern-web-guidance, tailwind-expert, modern-css-native-expert, design-system-architect.
  • Kualitas & Performa: performance-web-vitals, e2e-testing-expert, anti-slop, visual-ui-auditor.
  • Backend & APIs: js-backend-expert, database-orm-expert, typescript-expert.

Deskripsi

Panduan produksi untuk membangun aplikasi web performa tinggi menggunakan Svelte 5 dan SvelteKit 2+. Berfokus pada paradigma reaktivitas Runes secara menyeluruh ($state, $derived, $derived.by, $effect, $props, $bindable), komposisi Snippets pengganti slot lawas, progressive enhancement form actions (use:enhance), streaming promise server pada +page.server.ts, dan routing shallow (pushState) untuk modal URL-preserving.

Kondisi Pemicu

  • Membangun aplikasi baru menggunakan Svelte 5 dan SvelteKit 2.
  • Merefaktor kode lama Svelte 3/4 (let x = 0; $: doubled = x * 2;) ke sistem Runes Svelte 5.
  • Menggubah komponen UI modular menggunakan Snippets Svelte 5 alih-alih <slot> lawas.
  • Mengimplementasikan pengiriman data formulir atomik via Server Actions dengan fallback zero-JS.
  • Mengalirkan (streaming) data asinkron lambat ke klien tanpa memblokir rendering HTML SSR awal.

Implementasi Pola Kunci

1. Referensi Lengkap Runes Svelte 5

RuneFungsi & TujuanSintaks Lama Svelte 4
$state(nilai)State reaktif mendalam (deep reactive proxy)let nilai = ...
$state.raw(nilai)State reaktif dangkal (shallow untuk objek besar/imutable)Tidak tersedia
$derived(ekspresi)Nilai turunan ter-cache otomatis$: nilai = ekspresi
$derived.by(() => {})Kalkulasi turunan kompleks multi-baris$: { ... }
$effect(() => {})Efek samping pasca render DOM dengan siklus cleanuponMount, afterUpdate, $: { ... }
$effect.pre(() => {})Efek samping sebelum DOM di-updatebeforeUpdate
$props()Menerima props komponen secara terstruktur & type-safeexport let prop
$bindable()Memberi izin binding dua arah eksplisitBinding dua arah otomatis
$inspect(nilai)Inspeksi state mendalam saat mode pengembanganconsole.log(nilai) di $:

2. Komposisi Komponen dengan Svelte 5 Snippets (Tanpa Slot)

Pada Svelte 5, <slot> digantikan oleh Snippets bertipe (typed snippets):

<!-- src/lib/components/TabelData.svelte -->
<script lang="ts" generics="T">
  import type { Snippet } from 'svelte';

  interface Props {
    data: T[];
    kepala: Snippet;
    baris: Snippet<[T]>;
    kosong?: Snippet;
  }

  let { data, kepala, baris, kosong }: Props = $props();
</script>

<div class="overflow-x-auto rounded-xl border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900">
  <table class="w-full text-left text-sm">
    <thead class="border-b border-slate-200 dark:border-slate-800 bg-slate-50 dark:bg-slate-800/50 text-xs uppercase font-semibold text-slate-500">
      {@render kepala()}
    </thead>
    <tbody class="divide-y divide-slate-100 dark:divide-slate-800">
      {#each data as item}
        <tr class="hover:bg-slate-50 dark:hover:bg-slate-800/30 transition-colors">
          {@render baris(item)}
        </tr>
      {:else}
        {#if kosong}
          <tr>
            <td colspan="100%" class="p-8 text-center text-slate-400">
              {@render kosong()}
            </td>
          </tr>
        {/if}
      {/each}
    </tbody>
  </table>
</div>

3. Form Action SvelteKit 2 dengan Progressive Enhancement & State Optimistik

// src/routes/tugas/+page.server.ts
import { fail } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import { db } from '$lib/server/db';

export const load: PageServerLoad = async () => {
  return {
    daftarTugas: await db.tasks.findMany({ orderBy: { createdAt: 'desc' } }),
    metrikServer: ambilMetrikServer(), // Streamed Promise tanpa menunda payload HTML awal
  };
};

export const actions: Actions = {
  tambahTugas: async ({ request }) => {
    const data = await request.formData();
    const judul = data.get('judul')?.toString().trim();

    if (!judul || judul.length < 3) {
      return fail(400, { judul, error: 'Judul tugas minimal terdiri dari 3 karakter.' });
    }

    const tugasBaru = await db.tasks.create({ data: { title: judul, completed: false } });
    return { success: true, tugas: tugasBaru };
  },
};

async function ambilMetrikServer() {
  await new Promise((r) => setTimeout(r, 400));
  return { nodeAktif: 12, uptime: '99.99%' };
}
<!-- src/routes/tugas/+page.svelte -->
<script lang="ts">
  import { enhance } from '$app/forms';
  let { data, form } = $props();

  let sedangMenyimpan = $state(false);
  let daftarTugasOptimistik = $state([...data.daftarTugas]);

  $effect(() => {
    daftarTugasOptimistik = [...data.daftarTugas];
  });
</script>

<div class="max-w-xl mx-auto py-8 space-y-6">
  <h1 class="text-2xl font-bold">Daftar Tugas Proyek</h1>

  <form
    method="POST"
    action="?/tambahTugas"
    use:enhance={({ formData, cancel }) => {
      const judul = formData.get('judul')?.toString().trim();
      if (!judul) {
        cancel();
        return;
      }

      sedangMenyimpan = true;
      // Pembaruan UI Optimistik instan
      daftarTugasOptimistik = [{ id: `temp-${Date.now()}`, title: judul, completed: false }, ...daftarTugasOptimistik];

      return async ({ update }) => {
        sedangMenyimpan = false;
        await update();
      };
    }}
    class="flex gap-2"
  >
    <input
      name="judul"
      type="text"
      placeholder="Apa yang perlu dikerjakan?"
      required
      class="flex-1 px-3 py-2 border border-slate-300 dark:border-slate-700 rounded-md bg-transparent text-sm"
    />
    <button
      type="submit"
      disabled={sedangMenyimpan}
      class="px-4 py-2 bg-emerald-600 text-white font-medium rounded-md disabled:opacity-50 text-sm hover:bg-emerald-500 transition"
    >
      {sedangMenyimpan ? 'Menyimpan...' : 'Tambah Tugas'}
    </button>
  </form>

  {#if form?.error}
    <p class="text-sm font-semibold text-rose-600">{form.error}</p>
  {/if}

  <ul class="divide-y divide-slate-200 dark:divide-slate-800 border rounded-xl bg-white dark:bg-slate-900">
    {#each daftarTugasOptimistik as tugas (tugas.id)}
      <li class="p-3 text-sm flex items-center justify-between">
        <span>{tugas.title}</span>
        {#if tugas.id.startsWith('temp-')}
          <span class="text-xs text-slate-400 font-mono">Menyinkronkan...</span>
        {/if}
      </li>
    {/each}
  </ul>

  <!-- Menunggu data streaming metrik asinkron -->
  {#await data.metrikServer}
    <div class="p-4 border rounded-lg bg-slate-50 dark:bg-slate-800/40 text-xs animate-pulse text-slate-400">
      Memuat telemetri klaster server...
    </div>
  {:then metrik}
    <div class="p-4 border rounded-lg bg-white dark:bg-slate-900 text-xs flex justify-between font-mono">
      <span>Node Aktif: {metrik.nodeAktif}</span>
      <span>Tingkat Uptime: {metrik.uptime}</span>
    </div>
  {/await}
</div>

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Expert guide for automated and manual Web Accessibility (a11y) testing — axe-core, Pa11y, Playwright a11y, screen reader testing, and WCAG 2.2 Level AA/AAA compliance / Panduan ahli pengujian aksesibilitas web.

The English summary is being prepared. Showing the original description.

roedyrustam/vibes-plug112Updated Oct 22, 2026

Expert guide for intelligent model cascading and routing — complexity-scored task routing from Fast (Composer 2.5, Grok 4.7/4.6) to Medium (Gemini 4 Argon, GPT-5.6 Sol, Claude Opus 5.5) and High (Claude Sonnet 5.5, Claude Fable 5.1, Muse Wonder) / Panduan ahli untuk kaskade dan routing model cerdas.

The English summary is being prepared. Showing the original description.

roedyrustam/vibes-plug112Updated Oct 22, 2026

Expert guide for intelligent model cascading and routing — complexity-scored task routing from Flash/Haiku to Sonnet/Opus/Astra, dynamic escalation with quality gates, 40-60% token cost reduction while maintaining output quality / Panduan ahli untuk kaskade dan routing model cerdas — routing tugas berbasis skor kompleksitas dari Flash/Haiku ke Sonnet/Opus/Astra, eskalasi dinamis dengan gerbang kualitas, pengurangan biaya token 40-60% dengan kualitas output terjaga.

The English summary is being prepared. Showing the original description.

roedyrustam/vibes-plug112Updated Oct 22, 2026

Master guide for Affective Computing, emotional AI, and real-time sentiment analysis through native multimodal tokens (voice intonation and facial micro-expressions) / Panduan utama komputasi afektif, AI emosional, dan analisis sentimen real-time melalui token multimodal native.

The English summary is being prepared. Showing the original description.

roedyrustam/vibes-plug112Updated Oct 22, 2026

Expert guide for Affective Computing, emotional AI, and real-time sentiment analysis through native multimodal tokens (voice intonation and facial micro-expressions) / Panduan ahli komputasi afektif, AI emosional, dan analisis sentimen real-time melalui token multimodal native.

The English summary is being prepared. Showing the original description.

roedyrustam/vibes-plug112Updated Oct 22, 2026

Expert guide for AI-assisted coding workflows — agentic code generation, multi-agent code swarms, self-healing CI/CD, automated PR review, spec-to-code pipelines, codebase knowledge graphs, and human-in-the-loop approval gates / Panduan ahli untuk workflow pengkodean berbasis AI — generasi kode agentic, code swarm multi-agen, CI/CD self-healing, review PR otomatis, pipeline spec-to-code, knowledge graph codebase, dan gate persetujuan human-in-the-loop.

The English summary is being prepared. Showing the original description.

roedyrustam/vibes-plug112Updated Oct 22, 2026

See all skills by roedyrustam

Report a problem with this skill