Use Cases (Mis à jour: 02/06/2026)

Developper avec Svelte et SvelteKit dans Claude Code

Guide pratique Claude Code pour Svelte/SvelteKit: setup, runes, routage, form actions, tests et modifications sures.

Developper avec Svelte et SvelteKit dans Claude Code

Pourquoi Claude Code est utile avec SvelteKit

Svelte est un framework d’interface qui compile des composants declaratifs en JavaScript leger. SvelteKit ajoute la couche application: routage par fichiers, rendu serveur, fonctions load, form actions, endpoints et adaptateurs de deploiement. Dans une vraie application, une petite fonctionnalite touche souvent src/routes, src/lib/components, $lib/server, les types generes et les tests.

Claude Code est un outil de developpement agentique capable de lire un depot, modifier des fichiers et lancer des commandes. Avec SvelteKit, il est efficace si vous lui donnez un cadre precis: lire les fichiers concernes, expliquer le flux de donnees, proposer un plan, puis changer un petit perimetre. Une demande vague comme “construis une app” melange trop de decisions: UI, routage, base de donnees, securite et tests.

Le point le plus important pour debuter est Svelte 5. Les runes sont la syntaxe reactive actuelle: $props recoit les entrees du composant, $state declare l’etat mutable, $derived calcule des valeurs a partir de l’etat, et $effect sert aux effets cote navigateur. Cet article suit une petite application de taches et montre le setup, les composants, l’etat partage, le routage, les formulaires, les tests et les prompts a donner a Claude Code.

flowchart LR
  A["Ecrire une demande limitee"] --> B["Faire lire les fichiers a Claude Code"]
  B --> C["Modifier les composants Svelte"]
  C --> D["Verifier load/actions"]
  D --> E["Executer checks et tests"]
  E --> F["Relire git diff humainement"]

Setup du projet

Pour demarrer une nouvelle application SvelteKit, la voie officielle actuelle est la CLI Svelte: npx sv create my-app. Pour une application Svelte autonome avec Vite, le template svelte-ts de Vite reste utile. La documentation Vite indique que Vite demande Node.js 20.19+ ou 22.12+, donc mettez Node a jour avant d’analyser des erreurs de build.

npx sv create claude-svelte-demo
cd claude-svelte-demo
npm install
npm run dev

claude

Sur un depot que Claude Code ne connait pas encore, commencez par le plan mode. Il peut lire les fichiers et proposer une approche sans modifier le code source.

/plan
Je veux ajouter une liste de taches a ce projet SvelteKit.
Lis d'abord src/routes et src/lib, puis propose les fichiers a changer, le flux de donnees et le plan de tests.
N'edite pas encore les fichiers.
claude --permission-mode plan

Les conventions d’equipe doivent aller dans CLAUDE.md ou .claude/CLAUDE.md: gestionnaire de paquets, commandes de verification, preference pour Svelte 5 runes, usage de form actions, interdiction de commit sans demande explicite. Une regle concrete comme “lancer npm run check avant de finir” est plus utile qu’une consigne generale comme “code propre”.

Ecrire de petits composants Svelte 5

Le composant suivant peut etre colle dans src/lib/components/TaskCard.svelte. Il garde un contrat clair: une tache en entree et une fonction onToggle. Les libelles sont calcules avec $derived, et le bouton conserve aria-pressed pour l’accessibilite.

<!-- src/lib/components/TaskCard.svelte -->
<script lang="ts">
  type Task = {
    id: string;
    title: string;
    done: boolean;
    estimateMinutes: number;
    tags: string[];
  };

  let {
    task,
    onToggle
  }: {
    task: Task;
    onToggle: (id: string) => void;
  } = $props();

  let statusLabel = $derived(task.done ? 'Terminee' : 'Ouverte');
  let estimateLabel = $derived(`${Math.ceil(task.estimateMinutes / 15) * 15} min`);
</script>

<article class:done={task.done} class="task-card">
  <div>
    <p class="status">{statusLabel}</p>
    <h3>{task.title}</h3>
    <p>{estimateLabel}</p>
  </div>

  <ul aria-label="Etiquettes">
    {#each task.tags as tag}
      <li>{tag}</li>
    {/each}
  </ul>

  <button type="button" aria-pressed={task.done} onclick={() => onToggle(task.id)}>
    {task.done ? 'Rouvrir' : 'Terminer'}
  </button>
</article>

<style>
  .task-card {
    display: grid;
    gap: 0.75rem;
    border: 1px solid #ddd;
    border-radius: 0.5rem;
    padding: 1rem;
  }

  .done {
    background: #f2fff5;
  }

  .status {
    font-size: 0.875rem;
    font-weight: 700;
  }

  ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    list-style: none;
    padding: 0;
  }

  li {
    border-radius: 999px;
    background: #eef2ff;
    padding: 0.2rem 0.6rem;
  }
</style>

Demandez a Claude Code de conserver ce contrat:

Ameliore src/lib/components/TaskCard.svelte en conservant la syntaxe Svelte 5 runes.
Contraintes:
- Ne change pas le type Task ni la signature onToggle.
- Garde onclick et ne reviens pas a on:click.
- Garde aria-pressed sur le bouton.
- Ameliore seulement la mise en page et les cas vides.
- Propose ensuite un test de composant.

Cette precision evite les refactorings invisibles. Claude Code peut etre tres rapide, mais il doit savoir ce qu’il ne doit pas toucher.

Etat partage: runes d’abord, stores quand c’est justifie

Svelte 5 permet d’utiliser les runes dans des fichiers .svelte.ts. Ces modules sont pratiques pour partager un etat reactif ou extraire une logique reactive. svelte/store reste pertinent pour des flux asynchrones complexes, des abonnements manuels ou une integration avec des bibliotheques qui exposent deja des stores.

// src/lib/state/taskFilters.svelte.ts
export type TaskStatus = 'all' | 'open' | 'done';

export const taskFilters = $state({
  query: '',
  status: 'all' as TaskStatus,
  tag: ''
});

export function resetTaskFilters() {
  taskFilters.query = '';
  taskFilters.status = 'all';
  taskFilters.tag = '';
}
<!-- src/lib/components/TaskFilterPanel.svelte -->
<script lang="ts">
  import { resetTaskFilters, taskFilters } from '$lib/state/taskFilters.svelte';
</script>

<section aria-label="Filtres de taches">
  <label>
    Mot-cle
    <input bind:value={taskFilters.query} placeholder="Facture, article, revue..." />
  </label>

  <label>
    Statut
    <select bind:value={taskFilters.status}>
      <option value="all">Toutes</option>
      <option value="open">Ouvertes</option>
      <option value="done">Terminees</option>
    </select>
  </label>

  <button type="button" onclick={resetTaskFilters}>Reinitialiser</button>
</section>

Le piege classique est le rendu serveur. window, document et localStorage n’existent pas pendant SSR. Si un etat doit etre persiste dans le navigateur, protegez l’acces avec browser depuis $app/environment.

// src/lib/state/theme.svelte.ts
import { browser } from '$app/environment';

export const themeState = $state({
  theme: 'system' as 'system' | 'light' | 'dark'
});

export function loadTheme() {
  if (!browser) return;
  const saved = localStorage.getItem('theme');
  if (saved === 'light' || saved === 'dark' || saved === 'system') {
    themeState.theme = saved;
  }
}

export function saveTheme(nextTheme: typeof themeState.theme) {
  themeState.theme = nextTheme;
  if (browser) localStorage.setItem('theme', nextTheme);
}

Routage, load et frontiere serveur

SvelteKit utilise un routeur base sur le systeme de fichiers. src/routes/about cree /about, et src/routes/tasks/[slug] cree une page dynamique avec un parametre slug. Pour charger des donnees avant le rendu, utilisez un fichier voisin +page.server.ts. Le code qui touche une base de donnees, une cle secrete ou une API privilegiee doit rester dans $lib/server.

// src/lib/server/tasks.ts
export type Task = {
  id: string;
  slug: string;
  title: string;
  done: boolean;
  estimateMinutes: number;
  tags: string[];
};

const tasks: Task[] = [
  {
    id: 'task-1',
    slug: 'write-svelte-guide',
    title: "Rediger l'article SvelteKit",
    done: false,
    estimateMinutes: 45,
    tags: ['writing', 'svelte']
  }
];

export async function getTaskBySlug(slug: string) {
  return tasks.find((task) => task.slug === slug) ?? null;
}
// src/routes/tasks/[slug]/+page.server.ts
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
import { getTaskBySlug } from '$lib/server/tasks';

export const load: PageServerLoad = async ({ params }) => {
  const task = await getTaskBySlug(params.slug);

  if (!task) {
    error(404, 'Task not found');
  }

  return { task };
};
<!-- src/routes/tasks/[slug]/+page.svelte -->
<script lang="ts">
  import type { PageProps } from './$types';

  let { data }: PageProps = $props();
</script>

<svelte:head>
  <title>{data.task.title} | Tasks</title>
</svelte:head>

<article>
  <p>{data.task.done ? 'Terminee' : 'Ouverte'}</p>
  <h1>{data.task.title}</h1>
  <p>Estimation: {data.task.estimateMinutes} minutes</p>
</article>

Prompt utile:

Lis src/routes/tasks/[slug] et src/lib/server/tasks.ts.
Ajoute un champ dueDate a Task et affiche-le sur la page detail.
Garde l'acces aux donnees serveur dans $lib/server.
Ne renomme pas le dossier de route [slug].
Lance npm run check a la fin.

Form actions et amelioration progressive

Les form actions SvelteKit permettent d’exporter actions depuis +page.server.ts, puis de soumettre un <form method="POST"> au serveur. Le formulaire fonctionne sans JavaScript; use:enhance ameliore seulement l’experience quand JavaScript est disponible.

// src/routes/contact/+page.server.ts
import { fail } from '@sveltejs/kit';
import type { Actions } from './$types';

export const actions = {
  default: async ({ request }) => {
    const formData = await request.formData();
    const values = {
      name: String(formData.get('name') ?? '').trim(),
      email: String(formData.get('email') ?? '').trim(),
      message: String(formData.get('message') ?? '').trim()
    };

    const errors: Record<string, string> = {};
    if (values.name.length < 2) errors.name = 'Saisissez au moins 2 caracteres.';
    if (!values.email.includes('@')) errors.email = "Verifiez l'adresse email.";
    if (values.message.length < 10) errors.message = 'Saisissez au moins 10 caracteres.';

    if (Object.keys(errors).length > 0) {
      return fail(400, { values, errors });
    }

    console.log('New inquiry', values);
    return { success: true };
  }
} satisfies Actions;
<!-- src/routes/contact/+page.svelte -->
<script lang="ts">
  import { enhance } from '$app/forms';
  import type { PageProps } from './$types';

  let { form }: PageProps = $props();
</script>

{#if form?.success}
  <p role="status">Envoye. Nous repondrons sous 1 a 3 jours ouvrables.</p>
{/if}

<form method="POST" use:enhance>
  <label>
    Nom
    <input name="name" value={form?.values?.name ?? ''} aria-invalid={!!form?.errors?.name} />
  </label>
  {#if form?.errors?.name}<p>{form.errors.name}</p>{/if}

  <label>
    Email
    <input name="email" type="email" value={form?.values?.email ?? ''} aria-invalid={!!form?.errors?.email} />
  </label>
  {#if form?.errors?.email}<p>{form.errors.email}</p>{/if}

  <label>
    Message
    <textarea name="message" rows="5" aria-invalid={!!form?.errors?.message}>{form?.values?.message ?? ''}</textarea>
  </label>
  {#if form?.errors?.message}<p>{form.errors.message}</p>{/if}

  <button type="submit">Envoyer</button>
</form>

Ne declenchez pas d’effet de bord avec GET, n’exposez pas de secrets au navigateur, et n’affichez pas de contenu non nettoye avec {@html}. Dans le prompt, dites clairement: validation serveur conservee, fonctionnement sans JavaScript, attributs d’accessibilite conserves.

Tests, cas d’usage et pieges

La documentation Svelte indique que Vitest convient bien aux projets Vite et SvelteKit. Testing Library est utile pour tester le comportement visible par l’utilisateur; Playwright prend ensuite les parcours complets.

// src/lib/components/TaskCard.test.ts
import { fireEvent, render, screen } from '@testing-library/svelte';
import { describe, expect, it } from 'vitest';
import TaskCard from './TaskCard.svelte';

describe('TaskCard', () => {
  it('toggles the task when the button is clicked', async () => {
    let toggledId = '';

    render(TaskCard, {
      task: {
        id: 'task-1',
        title: "Ecrire l'article SvelteKit",
        done: false,
        estimateMinutes: 45,
        tags: ['writing']
      },
      onToggle: (id) => {
        toggledId = id;
      }
    });

    await fireEvent.click(screen.getByRole('button', { name: 'Terminer' }));
    expect(toggledId).toBe('task-1');
  });
});
npm run check
npm run test
npm run build
git diff -- src/lib src/routes
Cas d’usageBon travail pour Claude CodeRelecture humaine
Filtres adminEtat avec $state, vues calculees avec $derivedFiltres dans l’URL, champs caches par permissions
Blog ou CMS[slug], load, SEO et 404Nettoyage HTML, brouillons, apercus
Formulaires de leadsActions, validation, use:enhance, testsDonnees personnelles, anti-spam, notifications
Migration Svelte 4 vers 5Convertir quelques composants vers runesEviter une migration massive non relue

Les erreurs frequentes sont: demander trop a la fois, melanger Svelte 4 et Svelte 5, importer $lib/server dans un composant, utiliser $effect pour des calculs qui devraient etre $derived, et accepter des tests trop faibles. Cote monetisation, SvelteKit relie facilement contenu technique et formulaires de contact; pour un accompagnement, utilisez la page de consultation Claude Code. Continuez avec le guide de demarrage, les conseils TypeScript et les strategies de test.

Sources officielles et resultat teste

Pour verifier le comportement actuel, utilisez les sources officielles: Svelte docs, SvelteKit docs, SvelteKit form actions, Vite guide et Claude Code docs.

Lis la structure SvelteKit actuelle, puis change seulement ce perimetre.
Fichiers: src/routes/contact/+page.svelte et src/routes/contact/+page.server.ts
Objectif: ajouter un champ company au formulaire.
Contraintes:
- Garder Svelte 5 runes.
- Ne pas supprimer use:enhance.
- Ajouter la validation serveur.
- Ne pas changer le texte CTA ni les classes de layout.
- Lancer npm run check avant de finir.
Termine par 3 lignes: changements, risque, tests manquants.

En testant ce flux sur une petite app de taches SvelteKit, Masa a constate que le plan mode reduisait le plus les retours en arriere. Les consignes “garder runes”, “executer npm run check” et “ne pas commit” ont produit des diffs plus petits et plus faciles a relire.

#Claude Code #Svelte #SvelteKit #frontend #TypeScript
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.