Construire une carte interactive des trains de nuit en Europe avec SvelteKit et Leaflet

30 mars 2026 · 5 min de lecture

Mon blog Nomade sur Rails couvre le voyage en train et le nomadisme digital. Début 2026, le réseau de trains de nuit en Europe est en pleine expansion : European Sleeper lance le Paris-Berlin, ÖBB Nightjet investit 500 millions d’euros dans 33 nouvelles rames, de nouvelles lignes connectent les Balkans et la Turquie.

C’est un sujet dont je parle souvent autour de moi — la possibilité de traverser l’Europe en dormant dans un train, sans prendre l’avion. Mais à chaque fois, la même question revient : “Tu aurais une carte avec toutes les lignes ?” Et je n’avais rien de convaincant à montrer. Les cartes existantes sont soit incomplètes, soit peu ergonomiques, et aucune n’est en français. J’ai décidé de construire la mienne.

Le résultat : nomadesurrails.fr/trainsdenuit — une carte interactive qui recense 70 lignes actives, 22 opérateurs et 183 gares à travers l’Europe.

Pourquoi ce projet

Au-delà du besoin personnel, ce projet répondait à une opportunité SEO. L’analyse concurrentielle a révélé trois cartes interactives existantes (Back on Track , Nachtzugkarte , Daniel Freund ) mais aucune en français, et aucune avec des informations de réservation directes par opérateur.

Les mots-clés “carte trains de nuit Europe”, “trains de nuit au départ de Paris” et les requêtes liées aux nouvelles lignes 2026 représentent un trafic en croissance, porté par l’intérêt pour le voyage bas carbone.

Les choix techniques

SvelteKit plutôt qu’un plugin WordPress

Le blog Nomade sur Rails tourne sous WordPress. J’aurais pu développer un shortcode ou un plugin custom. Mais une carte interactive avec filtrage, recherche et synchronisation carte/liste demande beaucoup de réactivité côté client — exactement le terrain de jeu d’un framework JS moderne.

J’ai choisi SvelteKit 2 avec Svelte 5 pour plusieurs raisons :

  • Performance — Svelte compile en vanilla JS, pas de virtual DOM. Sur une carte avec 70+ polylines et 183 marqueurs, ça compte.
  • Adapter static — le site est pré-rendu en HTML statique au build. Pas de serveur Node en production, juste des fichiers servis depuis un CDN.
  • Réactivité déclarative — les stores Svelte rendent trivial le filtrage croisé entre la carte et la liste.

L’application est déployée en sous-répertoire du site WordPress (/trainsdenuit/) grâce au paramètre paths.base de SvelteKit.

Leaflet pour la cartographie

Leaflet 1.9 gère la carte interactive. Les tuiles viennent de CartoDB (Positron pour le thème clair, Dark Matter pour le sombre). Chaque route est rendue comme un polyline avec des coordonnées GPS réelles — pas des lignes droites entre deux points.

Les interactions sont synchronisées entre la carte et le panneau latéral : survoler une carte dans la liste met en surbrillance la ligne sur la carte, et cliquer une ligne sur la carte ouvre un popup avec les détails et le lien de réservation.

Données statiques en JSON

Toutes les données sont dans un fichier routes.json de 6500 lignes. Trois entités :

  • Opérateurs (22) — nom, couleur, pays, URL
  • Gares (183) — nom, ville, coordonnées GPS
  • Routes (77) — opérateur, gares de départ/arrivée/via, durée, fréquence, tracé GPS, lien de réservation

Pas de base de données, pas d’API. Les données changent peu (quelques mises à jour par an quand une ligne est ajoutée ou supprimée) et le fichier JSON est embarqué dans le build statique.

Les routes supprimées sont conservées dans les données avec un champ discontinued et une date. Elles sont masquées par défaut mais affichables via un filtre — utile pour le suivi historique du réseau.

Architecture de l’application

L’application suit une architecture simple en composants Svelte :

src/lib/
├── components/
│   ├── Map.svelte          # Carte Leaflet + marqueurs + polylines
│   ├── RouteList.svelte    # Panneau latéral avec filtres
│   ├── RouteCard.svelte    # Carte individuelle d'une ligne
│   ├── SearchBar.svelte    # Recherche par ville (autocomplete)
│   └── ThemeToggle.svelte  # Bascule dark/light
├── data/
│   └── routes.json         # Dataset complet
└── stores/
    ├── filters.js          # État des filtres (ville, opérateur)
    ├── theme.js            # Persistance du thème (localStorage)
    └── affiliate.js        # Health check des liens de réservation

L’état applicatif est géré par trois stores Svelte :

  • selectedCity et selectedOperator — les filtres actifs
  • filteredRoutes — un store dérivé qui recalcule automatiquement les routes visibles à chaque changement de filtre

Ce pattern de stores dérivés évite les cascades de mises à jour manuelles. Quand l’utilisateur sélectionne une ville dans la barre de recherche, le store filteredRoutes se recalcule, ce qui met à jour simultanément la liste des routes et les polylines affichées sur la carte.

SEO et contenu

Une carte interactive seule ne se positionne pas dans Google. La page inclut des sections de contenu en dessous de la carte :

  • Guide d’utilisation de la carte
  • Présentation des 22 opérateurs
  • Focus “Trains de nuit au départ de Paris”
  • Nouvelles lignes 2026
  • Guide de réservation et tarifs
  • 9 questions fréquentes en accordéon

Le tout est balisé en JSON-LD avec un schema TravelApplication et un schema FAQPage . Le contenu cible des requêtes informationnelles longue traîne en français.

Ce que j’en retiens

Ce projet illustre bien qu’un développeur backend peut livrer un produit frontend complet quand le besoin est clair. SvelteKit est un excellent choix pour les sites statiques interactifs : le rendu est rapide, le build produit des fichiers légers, et la courbe d’apprentissage est douce quand on vient du backend.

La carte est accessible sur nomadesurrails.fr/trainsdenuit .