Use Cases

Claude Code Svelte / SvelteKit dengan Claude Code

Pelajari tentang claude code svelte / sveltekit menggunakan Claude Code. Dilengkapi tips praktis dan contoh kode.

SveltepengembanganでClaude Codeを使うメリット

Svelte compilerベース framework 、少 tidakボイラープレート 高性能なUI pembangunan bisa dilakukan.Claude Code リアクティブ宣言やSvelteKit固有 routing・データロード pola 理解し、efisienなコード generate bisa dilakukan.

generate Sveltekomponen

> Svelte dengan modal付き gambargalerikomponen buatkan.
> gridtampilan、クリック dengan 拡大、キーボードnavigasidukungan dengan 。
<!-- ImageGallery.svelte -->
<script lang="ts">
  interface Image {
    id: string;
    src: string;
    alt: string;
    thumbnail: string;
  }

  export let images: Image[] = [];

  let selectedIndex = -1;
  let isModalOpen = false;

  $: selectedImage = selectedIndex >= 0 ? images[selectedIndex] : null;

  function openModal(index: number) {
    selectedIndex = index;
    isModalOpen = true;
  }

  function closeModal() {
    isModalOpen = false;
    selectedIndex = -1;
  }

  function navigate(direction: number) {
    selectedIndex = (selectedIndex + direction + images.length) % images.length;
  }

  function handleKeydown(e: KeyboardEvent) {
    if (!isModalOpen) return;
    switch (e.key) {
      case 'Escape': closeModal(); break;
      case 'ArrowLeft': navigate(-1); break;
      case 'ArrowRight': navigate(1); break;
    }
  }
</script>

<svelte:window on:keydown={handleKeydown} />

<div class="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4">
  {#each images as image, i}
    <button
      class="overflow-hidden rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
      on:click={() => openModal(i)}
    >
      <img
        src={image.thumbnail}
        alt={image.alt}
        class="h-48 w-full object-cover transition-transform hover:scale-105"
        loading="lazy"
      />
    </button>
  {/each}
</div>

{#if isModalOpen && selectedImage}
  <div
    class="fixed inset-0 z-50 flex items-center justify-center bg-black/80"
    on:click={closeModal}
    role="dialog"
    aria-modal="true"
    aria-label="gambar拡大tampilan"
  >
    <div class="relative max-h-[90vh] max-w-[90vw]" on:click|stopPropagation>
      <img
        src={selectedImage.src}
        alt={selectedImage.alt}
        class="max-h-[90vh] max-w-[90vw] object-contain"
      />
      <button
        class="absolute -left-12 top-1/2 -translate-y-1/2 rounded-full bg-white/20 p-2 text-white hover:bg-white/40"
        on:click={() => navigate(-1)}
        aria-label="前 gambar"
      >

      </button>
      <button
        class="absolute -right-12 top-1/2 -translate-y-1/2 rounded-full bg-white/20 p-2 text-white hover:bg-white/40"
        on:click={() => navigate(1)}
        aria-label="次 gambar"
      >

      </button>
      <button
        class="absolute -top-10 right-0 text-white hover:text-gray-300"
        on:click={closeModal}
        aria-label="Close"
      >
        Close
      </button>
    </div>
    <p class="absolute bottom-4 text-center text-white">
      {selectedIndex + 1} / {images.length}
    </p>
  </div>
{/if}

設計 Sveltestore

> Svelte store dengan tema dan penggunapengaturan manajemenして。
> localStoragepersistensi付き dengan 。
// stores/settings.ts
import { writable, derived } from 'svelte/store';
import { browser } from '$app/environment';

interface UserSettings {
  theme: 'light' | 'dark' | 'system';
  language: 'ja' | 'en';
  fontSize: 'sm' | 'md' | 'lg';
  sidebarCollapsed: boolean;
}

const defaultSettings: UserSettings = {
  theme: 'system',
  language: 'ja',
  fontSize: 'md',
  sidebarCollapsed: false,
};

function createSettingsStore() {
  const initial = browser
    ? JSON.parse(localStorage.getItem('settings') || 'null') || defaultSettings
    : defaultSettings;

  const { subscribe, set, update } = writable<UserSettings>(initial);

  return {
    subscribe,
    update(partial: Partial<UserSettings>) {
      update(current => {
        const next = { ...current, ...partial };
        if (browser) localStorage.setItem('settings', JSON.stringify(next));
        return next;
      });
    },
    reset() {
      set(defaultSettings);
      if (browser) localStorage.removeItem('settings');
    },
  };
}

export const settings = createSettingsStore();

// 派生store:実際 適用されるtema
export const effectiveTheme = derived(settings, ($settings) => {
  if ($settings.theme !== 'system') return $settings.theme;
  if (!browser) return 'light';
  return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
});

serverサイド機能 SvelteKit

> SvelteKit dengan ブログ データロード dan formアクション implementasikan.
// src/routes/blog/[slug]/+page.server.ts
import type { PageServerLoad, Actions } from './$types';
import { error, fail } from '@sveltejs/kit';
import { prisma } from '$lib/server/db';

export const load: PageServerLoad = async ({ params }) => {
  const post = await prisma.post.findUnique({
    where: { slug: params.slug },
    include: {
      author: { select: { name: true, avatar: true } },
      comments: {
        include: { author: { select: { name: true } } },
        orderBy: { createdAt: 'desc' },
      },
    },
  });

  if (!post) throw error(404, 'Post not found');

  return { post };
};

export const actions: Actions = {
  comment: async ({ request, params, locals }) => {
    const session = await locals.getSession();
    if (!session) return fail(401, { message: 'login diperlukan す' });

    const formData = await request.formData();
    const body = formData.get('body')?.toString();

    if (!body || body.length < 2) {
      return fail(400, { message: 'コメント 2文字以上input ください', body });
    }

    await prisma.comment.create({
      data: {
        body,
        postSlug: params.slug,
        authorId: session.user.id,
      },
    });

    return { success: true };
  },
};
<!-- src/routes/blog/[slug]/+page.svelte -->
<script lang="ts">
  import type { PageData, ActionData } from './$types';
  import { enhance } from '$app/forms';

  export let data: PageData;
  export let form: ActionData;
</script>

<article class="prose mx-auto max-w-3xl">
  <h1>{data.post.title}</h1>
  <p class="text-gray-500">
    {data.post.author.name} - {new Date(data.post.createdAt).toLocaleDateString('en-US')}
  </p>
  {@html data.post.content}
</article>

<section class="mx-auto mt-12 max-w-3xl">
  <h2 class="text-xl font-bold">コメント ({data.post.comments.length})</h2>

  <form method="POST" action="?/comment" use:enhance>
    <textarea
      name="body"
      rows="3"
      class="mt-4 w-full rounded border p-3"
      placeholder="コメント input..."
      value={form?.body ?? ''}
    />
    {#if form?.message}
      <p class="text-sm text-red-600">{form.message}</p>
    {/if}
    <button type="submit" class="mt-2 rounded bg-blue-600 px-4 py-2 text-white">
      送信
    </button>
  </form>

  {#each data.post.comments as comment}
    <div class="mt-4 rounded border p-4">
      <p class="font-medium">{comment.author.name}</p>
      <p class="mt-1 text-gray-700">{comment.body}</p>
    </div>
  {/each}
</section>

Testing

import { render, fireEvent } from '@testing-library/svelte';
import { describe, it, expect } from 'vitest';
import ImageGallery from './ImageGallery.svelte';

describe('ImageGallery', () => {
  const images = [
    { id: '1', src: '/img1.jpg', alt: 'Image 1', thumbnail: '/thumb1.jpg' },
    { id: '2', src: '/img2.jpg', alt: 'Image 2', thumbnail: '/thumb2.jpg' },
  ];

  it('should render all images', () => {
    const { getAllByRole } = render(ImageGallery, { props: { images } });
    expect(getAllByRole('button')).toHaveLength(2);
  });

  it('should open modal on click', async () => {
    const { getAllByRole, getByRole } = render(ImageGallery, { props: { images } });
    await fireEvent.click(getAllByRole('button')[0]);
    expect(getByRole('dialog')).toBeTruthy();
  });
});

Summary

Dengan Claude Code, Svelte / SvelteKit komponen、store、serverサイドロジック efisien pengembangan bisa dilakukan.Svelte リアクティブ宣言やSvelteKit固有 loadfungsi・formアクション juga Claude Code 正確 扱え.プロンプト 工夫 品質 高めるコツ プロンプトテクニック完全panduan silakan lihat.framework比較 興味 ada方 Claude Code vs GitHub Copilot juga ご覧.

Untuk Claude Codeの詳細はAnthropic公式dokumenをご覧ください。SvelteKitの公式panduan, lihat SvelteKit公式サイト.

#Claude Code #Svelte #SvelteKit #frontend #TypeScript