Skip to content
Back to skills

Dev Svelte Guide

ASecurity

Développement d'applications Svelte et SvelteKit avec réactivité native, stores, SSR, routing et transitions. Se déclenche avec "Svelte", "SvelteKit", "store Svelte", "réactivité Svelte", "$:", "svelte:component". Also triggers on "Svelte component", "SvelteKit routing", "Svelte stores".

  • 27 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 18, 2026
ai-agentstypescriptshellbashnodetestinggitapi

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 18, 2026

npx -y skills add khalilbenaz/claude-skills-collection --skill dev-svelte-guide --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dev Svelte Guide?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dev Svelte Guide
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/khalilbenaz-dev-svelte-guide/badge)](https://www.skillsdirectory.com/skills/khalilbenaz-dev-svelte-guide)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dev-svelte-guide
description: Développement d'applications Svelte et SvelteKit avec réactivité native, stores, SSR, routing et transitions. Se déclenche avec "Svelte", "SvelteKit", "store Svelte", "réactivité Svelte", "$:", "svelte:component". Also triggers on "Svelte component", "SvelteKit routing", "Svelte stores".
---

# Guide Svelte / SvelteKit

## Critères de décision : Svelte vs SvelteKit

| Besoin | Solution |
|---|---|
| Composant UI isolé, widget embarqué | Svelte seul, build library |
| SPA avec routing côté client | SvelteKit + `adapter-static` |
| Site statique / blog / docs | SvelteKit + prerender + `adapter-static` |
| Application full-stack (API + DB + auth) | SvelteKit + `adapter-node` ou `adapter-vercel` |
| SSR obligatoire (SEO, données fraîches) | SvelteKit, SSR activé par défaut |

## Workflow

### 1. Initialiser le projet

```bash
# SvelteKit (recommandé)
npx sv create my-app
cd my-app && npm install
npm run dev

# Svelte seul (lib ou widget)
npx degit sveltejs/template my-widget
```

Choisir TypeScript dès le début — la migration ultérieure est coûteuse.

### 2. Structurer les routes SvelteKit

```
src/
  routes/
    +layout.svelte          # layout racine (nav, providers)
    +layout.server.ts       # load() partagé (session, user)
    +page.svelte            # page /
    blog/
      +page.svelte          # /blog
      [slug]/
        +page.svelte        # /blog/:slug
        +page.server.ts     # load({ params }) côté serveur
  lib/
    components/             # composants réutilisables
    stores/                 # stores partagés
    utils/                  # helpers purs
  app.html                  # template HTML racine
```

Règle : tout ce qui touche DB, secrets ou sessions va dans `+page.server.ts` ou `+server.ts`, jamais dans `+page.ts` (exécuté côté client aussi).

### 3. Réactivité — Svelte 4 vs Svelte 5

**Svelte 4 (legacy)**
```svelte
<script>
  let count = 0;
  $: doubled = count * 2;
  $: if (count > 10) console.log('high');
</script>
```

**Svelte 5 — Runes (recommandé pour tout nouveau projet)**
```svelte
<script>
  let count = $state(0);
  const doubled = $derived(count * 2);

  $effect(() => {
    if (count > 10) console.log('high');
    return () => { /* cleanup */ };
  });
</script>

<button onclick={() => count++}>{count} × 2 = {doubled}</button>
```

Avantages runes : réactivité fine (pas de réexécution du composant entier), cleanup explicite, lisibilité accrue, compatible composants universels.

### 4. Stores — état partagé

```ts
// src/lib/stores/cart.ts
import { writable, derived } from 'svelte/store';

const items = writable<CartItem[]>([]);

export const cart = {
  subscribe: items.subscribe,
  add: (item: CartItem) => items.update(i => [...i, item]),
  remove: (id: string) => items.update(i => i.filter(x => x.id !== id)),
  clear: () => items.set([]),
};

export const total = derived(items, $items =>
  $items.reduce((sum, i) => sum + i.price, 0)
);
```

```svelte
<!-- Auto-souscription avec $store -->
<script>
  import { cart, total } from '$lib/stores/cart';
</script>
<p>Total : {$total} €</p>
```

Préférer le context API (`setContext/getContext`) quand le store n'est utile qu'à un sous-arbre — évite les fuites entre utilisateurs en SSR.

### 5. Data loading et form actions

```ts
// src/routes/products/[id]/+page.server.ts
import type { PageServerLoad, Actions } from './$types';
import { error, fail, redirect } from '@sveltejs/kit';

export const load: PageServerLoad = async ({ params, locals }) => {
  const product = await db.product.findUnique({ where: { id: params.id } });
  if (!product) error(404, 'Produit introuvable');
  return { product };
};

export const actions: Actions = {
  addToCart: async ({ request, locals }) => {
    const data = await request.formData();
    const qty = Number(data.get('qty'));
    if (!qty || qty < 1) return fail(422, { error: 'Quantité invalide' });
    await cartService.add(locals.user.id, params.id, qty);
    redirect(303, '/cart');
  }
};
```

```svelte
<!-- +page.svelte -->
<script>
  import { enhance } from '$app/forms';
  let { data, form } = $props();
</script>

<h1>{data.product.name}</h1>
{#if form?.error}<p class="error">{form.error}</p>{/if}

<form method="POST" action="?/addToCart" use:enhance>
  <input name="qty" type="number" value="1" min="1" />
  <button>Ajouter au panier</button>
</form>
```

`use:enhance` : soumission progressive — fonctionne sans JS, AJAX avec JS.

### 6. Transitions et animations

```svelte
<script>
  import { fade, fly, slide } from 'svelte/transition';
  import { flip } from 'svelte/animate';
  let visible = $state(true);
  let items = $state(['a', 'b', 'c']);
</script>

{#if visible}
  <div transition:fly={{ y: 20, duration: 300 }}>Contenu</div>
{/if}

{#each items as item (item)}
  <div animate:flip={{ duration: 250 }}>{item}</div>
{/each}
```

Pour les transitions de page (SvelteKit 2+) :
```ts
// src/hooks.client.ts
import { onNavigate } from '$app/navigation';
onNavigate(navigation => {
  if (!document.startViewTransition) return;
  return new Promise(resolve => {
    document.startViewTransition(async () => {
      resolve();
      await navigation.complete;
    });
  });
});
```

### 7. Composants avancés

```svelte
<!-- Slot nommé -->
<Card>
  <svelte:fragment slot="header">Titre</svelte:fragment>
  Contenu par défaut
</Card>

<!-- Composant dynamique -->
<svelte:component this={selectedComponent} {props} />

<!-- Context API (évite prop drilling) -->
<script>
  import { setContext, getContext } from 'svelte';
  setContext('theme', { primary: '#3b82f6' });
  // Dans un enfant :
  const theme = getContext('theme');
</script>
```

### 8. Tester

```bash
npm install -D @testing-library/svelte vitest jsdom
```

```ts
// src/lib/Counter.test.ts
import { render, fireEvent } from '@testing-library/svelte';
import Counter from './Counter.svelte';

test('incrémente au clic', async () => {
  const { getByRole } = render(Counter);
  const btn = getByRole('button');
  await fireEvent.click(btn);
  expect(btn.textContent).toBe('1');
});
```

Pour les routes SvelteKit, utiliser Playwright pour les tests E2E :
```bash
npx playwright test
```

### 9. Déployer

```bash
# Node.js (serveur autonome)
npm install -D @sveltejs/adapter-node

# Static (Netlify, GitHub Pages)
npm install -D @sveltejs/adapter-static

# Vercel / Cloudflare (auto-detect)
npm install -D @sveltejs/adapter-vercel
npm install -D @sveltejs/adapter-cloudflare
```

```ts
// svelte.config.js
import adapter from '@sveltejs/adapter-node';
export default { kit: { adapter: adapter() } };
```

Prerender sélectif :
```ts
// +page.ts
export const prerender = true;   // page statique
export const ssr = false;        // SPA shell uniquement
export const csr = false;        // HTML pur sans hydratation
```

## Garde-fous / Anti-patterns

- **Stores globaux + SSR** : un store module-level est partagé entre toutes les requêtes serveur — utiliser `setContext` ou initialiser le store dans `load()`.
- **Secrets dans `+page.ts`** : ce fichier s'exécute client ET serveur ; les clés API fuient dans le bundle. Toujours `+page.server.ts` pour les données sensibles.
- **Réactivité perdue sur objets** : en Svelte 4, `obj.prop = x` ne déclenche pas la réactivité si `obj` n'est pas réassigné — faire `obj = { ...obj, prop: x }`. En Svelte 5 avec `$state`, la réactivité profonde est native.
- **`invalidateAll()` trop large** : relance tous les `load()` de la page ; préférer `invalidate(url)` ciblé pour éviter des waterfalls réseau.
- **Mixage Svelte 4 et 5** : les runes (`$state`, `$derived`) ne sont disponibles qu'en mode rune (fichiers `.svelte` avec `<svelte:options runes />` ou projet créé avec Svelte 5). Ne pas mélanger `$:` et runes dans le même composant.
- **Oublier `use:enhance`** : sans lui, un `<form>` SvelteKit fait un rechargement complet de page — rend les actions inutilisables sans JS.

## Bonnes pratiques 2026

- **Svelte 5 + runes** pour tout nouveau code : réactivité fine, meilleure DX, composants universels (SSR + client sans divergence).
- **TypeScript strict** + `$types` générés automatiquement par SvelteKit pour `PageData`, `ActionData`, `LayoutData`.
- **`$app/state`** (SvelteKit 2.12+) remplace certains stores comme `$page` : `import { page } from '$app/state'` sans souscription.
- **Skeleton CSS / UnoCSS / Tailwind** : utiliser Tailwind via le preset officiel `@skeletonlabs/skeleton` ou `@tailwindcss/vite`.
- **Vite 6 / Rolldown** : SvelteKit 2.x supporte Rolldown-Vite pour des builds significativement plus rapides — activer via `vite.config.ts` quand disponible.
- **Progressive enhancement** systématique : forms avec `use:enhance`, navigation sans JS avec `<a>` standards, JS comme amélioration et non prérequis.


## Communication Rules — MANDATORY

- Ultra-concise. No filler, no preamble, no pleasantries.
- Never say "happy to help", "sure!", "great question", "let me", or similar.
- Tool first, talk second. Act before explaining.
- Result first. Lead with outcome, not process.
- Stop when done. No summary, no recap, no trailing commentary.
- No politeness wrappers. Direct and blunt.
- Minimum words. If one word works, do not use ten.
- No unsolicited explanations.
- No emoji unless asked.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.