Ce que vous saurez faire
- Comprendre l’approche Svelte (compilateur vs runtime)
- SvelteKit avec routing + SSR
- Runes (Svelte 5) et stores
- Déployer en production
Étape 1 — Pourquoi Svelte
Svelte compile les composants en JS vanilla optimisé. Pas de Virtual DOM, pas de hooks, bundle runtime minimal. Le framework disparaît au build.
Étape 2 — Créer un projet SvelteKit
npm create svelte@latest mon-app
# Skeleton + TypeScript + ESLint + Prettier + Vitest
cd mon-app
npm install
npm run dev
Étape 3 — Premier composant
<script lang="ts">
let nom = $state("Aminata");
let clics = $state(0);
let salutation = $derived(`Bonjour ${nom.trim()}`);
function incrementer() { clics++; }
</script>
<input bind:value={nom} />
<p>{salutation}</p>
<button onclick={incrementer}>Clics: {clics}</button>
<style>
button { background: #ff3e00; color: white; padding: .5rem 1rem; }
</style>
Étape 4 — Runes (Svelte 5)
<script lang="ts">
let clients = $state<{id:number; nom:string}[]>([]);
let recherche = $state("");
let filtres = $derived(clients.filter(c => c.nom.includes(recherche)));
$effect(() => {
fetch("/api/clients").then(r => r.json()).then(d => clients = d);
});
</script>
<input bind:value={recherche} placeholder="Filtrer..." />
{#each filtres as c (c.id)}
<div>{c.nom}</div>
{/each}
Étape 5 — Props et events
<!-- Carte.svelte -->
<script lang="ts">
let { titre, onselect }: { titre: string; onselect: (t: string) => void } = $props();
</script>
<article onclick={() => onselect(titre)}>
<h3>{titre}</h3>
</article>
Étape 6 — Routing SvelteKit
src/routes/
+layout.svelte layout global
+page.svelte /
clients/
+page.svelte /clients
+page.server.ts loader serveur
[id]/+page.svelte /clients/42
Étape 7 — Loader serveur
// src/routes/clients/+page.server.ts
import type { PageServerLoad } from "./$types";
import { db } from "$lib/db";
export const load: PageServerLoad = async () => {
const clients = await db.query("SELECT id, nom, ville FROM clients");
return { clients: clients.rows };
};
<!-- +page.svelte -->
<script lang="ts">
let { data } = $props();
</script>
<h1>Clients</h1>
<ul>
{#each data.clients as c}<li>{c.nom}</li>{/each}
</ul>
Étape 8 — Form actions
// +page.server.ts
import { fail, redirect } from "@sveltejs/kit";
export const actions = {
creer: async ({ request }) => {
const data = await request.formData();
const nom = data.get("nom")?.toString();
if (!nom) return fail(400, { manque: true });
const r = await db.query("INSERT INTO clients(nom) VALUES($1) RETURNING id", [nom]);
throw redirect(303, `/clients/${r.rows[0].id}`);
},
};
<form method="POST" action="?/creer">
<input name="nom" required />
<button>Créer</button>
</form>
Étape 9 — Stores custom
// $lib/panier.svelte.ts
class Panier {
items = $state<{id:string;qty:number;prix:number}[]>([]);
total = $derived(this.items.reduce((s, i) => s + i.qty * i.prix, 0));
ajouter(id: string, prix: number) {
const e = this.items.find(i => i.id === id);
if (e) e.qty++;
else this.items.push({id, prix, qty: 1});
}
}
export const panier = new Panier();
Étape 10 — Animations
<script>
import { fly, fade } from "svelte/transition";
import { flip } from "svelte/animate";
let liste = $state(["A","B","C"]);
</script>
{#each liste as item (item)}
<div in:fly={{y:20,duration:300}} out:fade animate:flip>{item}</div>
{/each}
Étape 11 — Build et déploiement
npm run build
npm run preview
# Adapters: vercel, cloudflare, node, static...
npm install -D @sveltejs/adapter-vercel
# svelte.config.js: import adapter from '@sveltejs/adapter-vercel';
# Déploiement
npx vercel --prod
Étape 12 — Tests Vitest
import { render, screen } from "@testing-library/svelte";
import { test, expect } from "vitest";
import Carte from "./Carte.svelte";
test("rend le titre", () => {
render(Carte, { titre: "Formation" });
expect(screen.getByText("Formation")).toBeInTheDocument();
});
Checklist
✓ Svelte 5 runes ($state, $derived, $effect, $props)
✓ Séparation +page.svelte (UI) / +page.server.ts (data)
✓ Form actions pour submits sans fetch côté client
✓ Stores classes pour état partagé complexe
✓ Transitions intégrées (fly, fade, flip)
✓ Tests Vitest + Testing Library
✓ Adapter selon cible (Vercel, CF, Node)
Étape 1 : comprendre pourquoi choisir Svelte en 2026
Svelte est sorti de l’effet de mode pour devenir un choix de framework front sérieux. La version 5, stable depuis octobre 2024, introduit les « runes » ($state, $derived, $effect) qui remplacent l’ancien système de réactivité. Pour une PME ouest-africaine qui veut un site rapide à charger sur des connexions 3G de Dakar ou de Bamako, le bundle Svelte (souvent 30 % plus léger que React équivalent) est un argument concret.
Le critère de choix n’est pas idéologique : utilisez Svelte si votre équipe est petite (1 à 3 développeurs front), si vous voulez un onboarding rapide, et si la performance perçue compte (e-commerce, application interne PME). Restez sur React si vous recrutez sur un marché abondant en développeurs React.
Étape 2 : créer le projet SvelteKit
SvelteKit est le framework officiel autour de Svelte (équivalent de Next.js pour React). Il gère le routing, le SSR, l’API. La commande de création en 2026 utilise npx sv create (et non plus npm create svelte@latest qui est déprécié).
npx sv create mon-app
cd mon-app
npm install
npm run dev -- --open
Choisissez « SvelteKit minimal » si vous démarrez de zéro, « SvelteKit demo app » si vous voulez voir un exemple complet. Activez TypeScript (recommandé), ESLint et Prettier. Le navigateur s’ouvre sur http://localhost:5173 avec la page d’accueil par défaut. Si la page s’affiche, votre environnement est correct.
Étape 3 : maîtriser les runes (la nouveauté de Svelte 5)
Les runes remplacent l’ancien let count = 0; $: doubled = count * 2;. La nouvelle syntaxe est plus explicite et évite les pièges de réactivité implicite.
<script>
let count = $state(0);
let doubled = $derived(count * 2);
$effect(() => {
console.log('count a changé:', count);
});
</script>
<button onclick={() => count++}>{count} (doublé : {doubled})</button>
Le bon résultat se reconnaît à : cliquer sur le bouton incrémente le compteur, l’affichage du double se met à jour automatiquement, et la console log à chaque clic. Si rien ne bouge, vérifiez que vous êtes bien en Svelte 5 (npm ls svelte doit afficher 5.x).
Étape 4 : organiser le routing par dossiers
SvelteKit utilise le routing par système de fichiers. Chaque dossier dans src/routes/ devient une URL. Un fichier +page.svelte est la page elle-même, +layout.svelte le gabarit qui l’entoure, +page.server.ts le code qui ne s’exécute que côté serveur.
src/routes/
├── +layout.svelte // gabarit global (header, footer)
├── +page.svelte // page d'accueil "/"
├── produits/
│ ├── +page.svelte // "/produits"
│ └── [slug]/
│ └── +page.svelte // "/produits/sac-en-cuir"
└── api/
└── contact/
└── +server.ts // endpoint POST /api/contact
Cette structure rend l’arborescence du projet immédiatement lisible pour un nouveau développeur. Pas de configuration de routeur à apprendre.
Étape 5 : charger des données depuis une API
Pour une PME au Sénégal qui interroge une API Odoo ou une base Supabase, la fonction load exportée depuis +page.server.ts récupère les données côté serveur avant le rendu. Le HTML arrive déjà rempli au navigateur, ce qui économise un aller-retour sur connexion lente.
// src/routes/produits/+page.server.ts
export async function load({ fetch }) {
const r = await fetch('https://api.mapme.sn/produits');
const produits = await r.json();
return { produits };
}
<!-- src/routes/produits/+page.svelte -->
<script>
let { data } = $props();
</script>
{#each data.produits as p}
<article>{p.nom} — {p.prix_fcfa} FCFA</article>
{/each}
L’utilisateur reçoit la liste de produits dès le premier paint. Pas d’écran de chargement, pas de loader vide, ce qui change l’expérience perçue sur une connexion 3G d’Abidjan.
Étape 6 : gérer les formulaires avec actions
SvelteKit propose un système d’actions de formulaire qui marche même JavaScript désactivé (utile sur navigateurs anciens encore courants en zone rurale ouest-africaine).
// src/routes/contact/+page.server.ts
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
const email = data.get('email');
// envoi vers une queue, un webhook WhatsApp, etc.
return { success: true };
}
};
Côté composant, un simple <form method="POST"> déclenche l’action. SvelteKit enrichit automatiquement avec une soumission AJAX si JavaScript est actif, sans changer le code.
Étape 7 : construire et déployer sur Coolify
Pour la production, l’adapter le plus simple est @sveltejs/adapter-node qui produit un serveur Node.js déployable sur n’importe quel VPS. Sur un VPS Hetzner CX11 (1 vCPU, 2 Go, environ 4 EUR/mois soit 2 625 FCFA) géré par Coolify, le déploiement prend 3 minutes.
npm install -D @sveltejs/adapter-node
# dans svelte.config.js : import adapter from '@sveltejs/adapter-node';
npm run build
# Coolify détecte automatiquement le projet Node, build et lance "node build/"
Le marqueur de succès : l’URL publique de votre application (ex: https://app.mapme.sn) répond avec le HTML pré-rendu et un Lighthouse Performance supérieur à 90.
Étape 8 : optimiser pour les connexions africaines
Trois leviers concrets : activer la compression Brotli sur Traefik (gain 20 % sur le poids transféré), précharger les polices critiques avec <link rel="preload">, et utiliser le composant <enhanced:img> de SvelteKit qui sert WebP/AVIF selon le navigateur. Sur une connexion 4G typique de Dakar (10 Mbps mais latence 200 ms), ces trois optimisations ramènent le LCP sous 2,5 secondes.
Pour étoffer le tableau, consultez notre guide Coolify sur Hetzner et le tutoriel sauvegarde Postgres vers S3 pour héberger l’API qui sert vos données. Avec ce stack (SvelteKit + Node + Postgres + Coolify), une PME ouest-africaine déploie une application moderne pour moins de 10 EUR/mois (6 560 FCFA), maintenable par un développeur unique pendant des années.
Étape 1 : comprendre pourquoi choisir Svelte en 2026
Svelte est sorti de l’effet de mode pour devenir un choix de framework front sérieux. La version 5, stable depuis octobre 2024, introduit les « runes » ($state, $derived, $effect) qui remplacent l’ancien système de réactivité. Pour une PME ouest-africaine qui veut un site rapide à charger sur des connexions 3G de Dakar ou de Bamako, le bundle Svelte (souvent 30 % plus léger que React équivalent) est un argument concret.
Le critère de choix n’est pas idéologique : utilisez Svelte si votre équipe est petite (1 à 3 développeurs front), si vous voulez un onboarding rapide, et si la performance perçue compte (e-commerce, application interne PME). Restez sur React si vous recrutez sur un marché abondant en développeurs React.
Étape 2 : créer le projet SvelteKit
SvelteKit est le framework officiel autour de Svelte (équivalent de Next.js pour React). Il gère le routing, le SSR, l’API. La commande de création en 2026 utilise npx sv create (et non plus npm create svelte@latest qui est déprécié).
npx sv create mon-app
cd mon-app
npm install
npm run dev -- --open
Choisissez « SvelteKit minimal » si vous démarrez de zéro, « SvelteKit demo app » si vous voulez voir un exemple complet. Activez TypeScript (recommandé), ESLint et Prettier. Le navigateur s’ouvre sur http://localhost:5173 avec la page d’accueil par défaut. Si la page s’affiche, votre environnement est correct.
Étape 3 : maîtriser les runes (la nouveauté de Svelte 5)
Les runes remplacent l’ancien let count = 0; $: doubled = count * 2;. La nouvelle syntaxe est plus explicite et évite les pièges de réactivité implicite.
<script>
let count = $state(0);
let doubled = $derived(count * 2);
$effect(() => {
console.log('count a changé:', count);
});
</script>
<button onclick={() => count++}>{count} (doublé : {doubled})</button>
Le test concluant : cliquer sur le bouton incrémente le compteur, l’affichage du double se met à jour automatiquement, et la console log à chaque clic. Si rien ne bouge, vérifiez que vous êtes bien en Svelte 5 (npm ls svelte doit afficher 5.x).
Étape 4 : organiser le routing par dossiers
SvelteKit utilise le routing par système de fichiers. Chaque dossier dans src/routes/ devient une URL. Un fichier +page.svelte est la page elle-même, +layout.svelte le gabarit qui l’entoure, +page.server.ts le code qui ne s’exécute que côté serveur.
src/routes/
├── +layout.svelte // gabarit global (header, footer)
├── +page.svelte // page d'accueil "/"
├── produits/
│ ├── +page.svelte // "/produits"
│ └── [slug]/
│ └── +page.svelte // "/produits/sac-en-cuir"
└── api/
└── contact/
└── +server.ts // endpoint POST /api/contact
Cette structure rend l’arborescence du projet immédiatement lisible pour un nouveau développeur. Pas de configuration de routeur à apprendre.
Étape 5 : charger des données depuis une API
Pour une PME au Sénégal qui interroge une API Odoo ou une base Supabase, la fonction load exportée depuis +page.server.ts récupère les données côté serveur avant le rendu. Le HTML arrive déjà rempli au navigateur, ce qui économise un aller-retour sur connexion lente.
// src/routes/produits/+page.server.ts
export async function load({ fetch }) {
const r = await fetch('https://api.mapme.sn/produits');
const produits = await r.json();
return { produits };
}
<!-- src/routes/produits/+page.svelte -->
<script>
let { data } = $props();
</script>
{#each data.produits as p}
<article>{p.nom} — {p.prix_fcfa} FCFA</article>
{/each}
L’utilisateur reçoit la liste de produits dès le premier paint. Pas d’écran de chargement, pas de loader vide, ce qui change l’expérience perçue sur une connexion 3G d’Abidjan.
Étape 6 : gérer les formulaires avec actions
SvelteKit propose un système d’actions de formulaire qui marche même JavaScript désactivé (utile sur navigateurs anciens encore courants en zone rurale ouest-africaine).
// src/routes/contact/+page.server.ts
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
const email = data.get('email');
// envoi vers une queue, un webhook WhatsApp, etc.
return { success: true };
}
};
Côté composant, un simple <form method="POST"> déclenche l’action. SvelteKit enrichit automatiquement avec une soumission AJAX si JavaScript est actif, sans changer le code.
Étape 7 : construire et déployer sur Coolify
Pour la production, l’adapter le plus simple est @sveltejs/adapter-node qui produit un serveur Node.js déployable sur n’importe quel VPS. Sur un VPS Hetzner CX11 (1 vCPU, 2 Go, environ 4 EUR/mois soit 2 625 FCFA) géré par Coolify, le déploiement prend 3 minutes.
npm install -D @sveltejs/adapter-node
# dans svelte.config.js : import adapter from '@sveltejs/adapter-node';
npm run build
# Coolify détecte automatiquement le projet Node, build et lance "node build/"
Validation pratique : l’URL publique de votre application (ex: https://app.mapme.sn) répond avec le HTML pré-rendu et un Lighthouse Performance supérieur à 90.
Étape 8 : optimiser pour les connexions africaines
Trois leviers concrets : activer la compression Brotli sur Traefik (gain 20 % sur le poids transféré), précharger les polices critiques avec <link rel="preload">, et utiliser le composant <enhanced:img> de SvelteKit qui sert WebP/AVIF selon le navigateur. Sur une connexion 4G typique de Dakar (10 Mbps mais latence 200 ms), ces trois optimisations ramènent le LCP sous 2,5 secondes.
Lectures complémentaires, consultez notre guide Coolify sur Hetzner et le tutoriel sauvegarde Postgres vers S3 pour héberger l’API qui sert vos données. Avec ce stack (SvelteKit + Node + Postgres + Coolify), une PME ouest-africaine déploie une application moderne pour moins de 10 EUR/mois (6 560 FCFA), maintenable par un développeur unique pendant des années.