Use Cases

Claude Code के साथ Claude Code Svelte / SvelteKit

Claude Code का उपयोग करके claude code svelte / sveltekit सीखें। Practical tips और code examples शामिल हैं।

SveltedevelopmentでClaude Code use करनाメリット

Svelteはコンパイラベースのframeworkで、कमボイラープレートで高性能なUI build किया जा सकता है。Claude Codeはリアクティブ宣言やSvelteKit固有のrouting・dataロードのpatternを理解し、効率的なcode generateでき है।

Sveltecomponentのgenerate

> Svelteでmodal付きの画像ギャラリーcomponentをबनाओ。
> griddisplay、クリックで拡大、keyボードnavigationsupportで。
<!-- 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="画像拡大display"
  >
    <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="पहलेの画像"
      >
        ←
      </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="अगलाの画像"
      >
        →
      </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}

Svelteストアの設計

> Svelteのストアでthemeとusersettingsをmanagementして。
> localStorage永続化付きで。
// 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();

// 派生ストア:actually適用されるtheme
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';
});

SvelteKitのserverサイドfeatures

> SvelteKitでブlogのdataロードとformアクションをimplement करो。
// 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: 'logインがज़रूरीです' });

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

    if (!body || body.length < 2) {
      return fail(400, { message: 'コメントは2文字以ऊपर入力してください', 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="コメントを入力..."
      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>

test

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

Claude Code का उपयोग करके、Svelte / SvelteKitのcomponent、ストア、serverサイドロジックをefficientlydevelopmentでき है।Svelteのリアクティブ宣言やSvelteKit固有のloadfunction・formアクションもClaude Codeは正確に扱え है।プロンプトの工夫で品質を高めるコツはプロンプトテクニックcomplete guideをदेखें。framework比較に興味がある方はClaude Code vs GitHub Copilotもदेखें。

Claude Codeके details के लिएAnthropicofficial documentationदेखें。SvelteKitの公式ガイドはSvelteKit公式サイトをदेखें。

#Claude Code #Svelte #SvelteKit #frontend #TypeScript
मुफ़्त

मुफ़्त PDF: 5 मिनट में Claude Code चीटशीट

बस अपना ईमेल दर्ज करें और हम तुरंत A4 एक-पृष्ठ चीटशीट PDF भेज देंगे।

हम आपकी व्यक्तिगत जानकारी की सुरक्षा करते हैं और स्पैम नहीं भेजते।

Masa

लेखक के बारे में

Masa

Claude Code का गहराई से उपयोग करने वाले इंजीनियर। claudecode-lab.com चलाते हैं, जो 10 भाषाओं में 2,000 से अधिक पेजों वाला टेक मीडिया है।