Guide Svelte SEO

«Svelte alone is client-side rendered — content isn't in the raw HTML. SvelteKit fixes that with SSR by default. Rendering modes, svelte:head, load functions, adapters, sitemaps, and the SPA-mode trap.» _(Traduction)_ (Résumé en français du champ description : le texte source est conservé pour relecture francophone.)

Première publication : 26 juin 2026 · Dernière mise à jour : 3 août 2026 · Avancé

«Svelte SEO hinges on one distinction: plain Svelte is client-side rendered (a blank HTML shell), while SvelteKit renders on the server by default and ships full HTML. Use SvelteKit for anything that needs to rank. Manage metadata with svelte:head, fetch SEO data in +page.server.js load functions, pick the right adapter, and never ship SPA fallback mode (ssr: false) — the SvelteKit docs themselves warn it has large negative SEO impacts.» _(Traduction)_ (Résumé en français du champ tldr : le texte source est conservé pour relecture francophone.)

TL;DR — Svelte SEO est vraiment a SvelteKit conversation. Bare Svelte est CSR-seulement — contenu n’est pas dans le raw HTML. SvelteKit defaults à SSR, prend en charge prerendering (SSG) per route, et lets vous mix modes. Manage metadata avec <svelte:head> et feed il depuis +page.server.js charger functions donc il lands dans le initial HTML. Le sharpest trap: adapter-static avec ssr: false fait pas prerender — il produces vide shells; SSR doit stay on during le construire. SvelteKit’s propre docs warn SPA fallback a “grand negative performances et SEO impacts.” Utiliser History API routing (le par défaut), configurer trailingSlash, et pick an adapter à match — static pour contenu, node/vercel/cloudflare pour SSR.

Preuve à l’appui de cette affirmation The article's described svelte-seo capabilities must be evaluated against the platform's current documentation rather than assumed to be search-engine behavior. Portée : Platform-specific capability documentation. Niveau de confiance : élevé · Vérifié : SvelteKit page options Preuve à l’appui de cette affirmation Regardless of platform, Google needs crawlable URLs, accessible rendered content, descriptive metadata, and valid search directives. Portée : Google requirements independent of platform. Niveau de confiance : élevé · Vérifié : Google Search Central: SEO Starter Guide

«## Svelte is not SvelteKit — and for SEO that’s everything » (Traduction) (Résumé en français de la section dix-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«Svelte is a compiler. It turns your .svelte components into lean vanilla JavaScript with no virtual DOM and no runtime library shipped to the browser. That gives Svelte a real performance edge — but it’s a bundle-size optimization, not a rendering one. A plain Svelte app (Vite-bundled, no meta-framework) is still a client-side-rendered SPA: the server returns a blank HTML shell and the browser constructs the page. View source on one and your content isn’t there. » (Traduction) (Résumé en français de la section vingt, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«This is the #1 source of confusion when people search “Svelte SEO.” The compile step doesn’t put content in the HTML. SvelteKit does. SvelteKit is Svelte’s official meta-framework — the equivalent of Next.js for React or Nuxt for Vue — and it renders pages on the server by default, shipping fully populated HTML before any JavaScript runs. It adds SSR, static prerendering, file-based routing, load functions, and deployment adapters. The headline: bare Svelte = CSR-only; SvelteKit = SSR-first. Everything else in this guide assumes SvelteKit. » (Traduction) (Résumé en français de la section vingt et un, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«Two scoping notes worth stating precisely, because they’re where generic “Svelte SEO” advice goes wrong: SvelteKit’s rendering options (ssr, csr, prerender, trailingSlash) are set per route and inherit hierarchically — a +layout.js or +layout.server.js can set a default for everything beneath it, and a child route can override it. So “is this SvelteKit site SEO-friendly” isn’t a project-level question; check the specific route. And of SvelteKit’s rendering options, it’s specifically ssr: false — not SSR being merely absent, and not “using SvelteKit” in general — that the docs tie to an empty output: “If you set ssr to false, it renders an empty ‘shell’ page instead.” This guide is current for Svelte 5.x and SvelteKit 2.x (the current majors as of this update); Svelte 5 made runes the default reactivity model, but runes are a component-authoring concern, not a rendering mode — they don’t change any of the SEO guidance below. » (Traduction) (Résumé en français de la section vingt-deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«Why the rendering mode matters comes straight from how search engines work. Google processes JavaScript in three phases — crawling, rendering, and indexing — and “all pages with a 200 HTTP status code are sent to the rendering queue, no matter whether JavaScript is present on the page.” The render queue adds a delay, and as Google’s own guidance puts it, “server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript.” That last clause is doing a lot of work in 2026 — see the AI-crawler section. » (Traduction) (Résumé en français de la section vingt-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«## The four rendering modes in SvelteKit » (Traduction) (Résumé en français de la section vingt-quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«SvelteKit’s strength is that rendering is a per-route decision via page options. These options are hierarchical: set a default in a +layout.js/+layout.server.js and every nested route inherits it, unless a child route exports its own value to override it. Check the option that actually applies to the specific route you care about — not just the value set at the top of the project. » (Traduction) (Résumé en français de la section vingt-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«- SSR (the default). Pages are rendered server-side and the full HTML is in the initial response. Best for dynamic, personalized, or frequently changing content. This is on unless you turn it off. » (Traduction) (Résumé en français de la section vingt-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- Prerender (export const prerender = true). Pages are generated as static HTML at build time. Maximum speed and maximum crawlability — ideal for blog posts, docs, and marketing pages. Crucially, prerendering is SSR run at build time, so SSR must remain enabled for it to work. » (Traduction) (Résumé en français de la section vingt-six, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- SPA fallback (ssr: false). A single-page-app shell with no server rendering. The SvelteKit docs are blunt that this mode “has large negative performance and SEO impacts” and is really meant for things like wrapping in a mobile app — not for content you want indexed. » (Traduction) (Résumé en français de la section vingt-six, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- Hybrid. Mix modes per route: prerender your marketing pages, SSR your product pages, run an SPA-style admin behind a login. This is SvelteKit’s killer feature — you don’t pick one rendering mode for the whole site. » (Traduction) (Résumé en français de la section vingt-six, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)

«## The ssr: false trap (the mistake to avoid) » (Traduction) (Résumé en français de la section vingt-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Ce est le la plupart expensive misunderstanding dans SvelteKit SEO, donc il obtient son propre section. Personnes reach pour adapter-static à “make a static site,” et alors définir ssr: false thinking ils sont getting prerendered HTML. Ils ne sont pas.

Prerendering est rendu côté serveur executed à construire temps. Si vous disable SSR, là n’est pashing à rendre — le docs sont explicit que ssr: false “renders an vide ‘shell’ page à la place,” et c’est exactly ce que adapter-static alors ships as votre prerendered sortie. Le contenu seulement apparaît une fois le client-side JavaScript exécute, qui puts vous correct back dans CSR territory (avec tout son robot d’exploration problèmes) despite having a “static” construire. Le règle: avec adapter-static, laisser ssr on (son par défaut) donc prerendering outputs réel HTML. Utiliser ssr: false seulement quand vous genuinely vouloir an SPA shell et accept le SEO coût.

Managing metadata with <svelte:head>

SvelteKit a a special element, <svelte:head>, que injects contenu dans le document <head> — et vous ne pas besoin a tiers library à manage votre titre et meta balises. Chaque page devrait ont a unique <title> et <meta name="description">, plus canonical, Ouvrir Graph, Twitter Card, hreflang, robots directives, et JSON-LD as nécessaire.

Le modèle le official docs recommend pour dynamic metadata:

  1. Retourner SEO metadata from a +page.server.js load() function.
  2. Accès it via page.data in votre layout.
  3. Render it in <svelte:head> in the root +layout.svelte.
<!-- +layout.svelte -->
<script>
  import { page } from '$app/state';
</script>

<svelte:head>
  <title>{page.data.title}</title>
  <meta name="description" content={page.data.description} />
  <link rel="canonical" href={page.data.canonical} />
</svelte:head>

Si vous’d plutôt utiliser a component wrapper, le tiers svelte-seo package wraps <svelte:head> avec props pour le courant balises — mais c’est a convenience, pas a requirement.

<svelte:head> obtient votre balises dans le head; il ne fait pas vérifier vous obtenu les correct. c’est encore votre job: confirmer chaque route renders a unique titre et description (pas un inherited depuis le layout par accident), que le canonical vous emit est consistent entre le direct-requête HTML et ce que a client-side navigation renders, et que robots directives et JSON-LD sont présent dans le raw réponse — pas seulement visible après hydration.

Charger functions: où vous récupérer SEO données matters

Ce est le metadata bug que bites personnes. +page.server.js load() exécute on le serveur, donc son données est dans le initial HTML réponse. +page.js load() exécute on le serveur pour le premier rendre et on le client during client-side navigation. Le mistake est fetching votre titre/description/canonical dans a <script> bloquer avec onMount() — que exécute client-side seulement, donc le initial HTML ships avec aucun metadata et le robot d’exploration voit rien on le premier récupérer. Récupérer SEO-critical données dans a load function (serveur charger pour n’importe quoi que doit être dans le premier réponse), pas dans onMount.

ne pas assume le fichier nom alone proves le boundary, though — +page.js load() aussi exécute on le serveur pour le premier requête, alors re-exécute client-side on navigation, et son retourner valeur a à survive serialization à être reused safely on le client. Si SEO-critical données ever dépend on a valeur que n’est pas safely serializable, vérifier les deux le direct-requête HTML et a client-navigated view de le même route, pas simplement un or le autre.

Routing and Structure d’URL

  • Fichier-based routing avec [param] pour dynamic segments donne vous clean, predictable URLs.
  • History API routing est le par défaut — SvelteKit ne fait pas utiliser hash/fragment routing, et c’est exactly ce que vous vouloir. Google ne peut pas reliably resolve hash-based (#/page) URLs, donc History API routing est le SEO-sûr choice et SvelteKit rend il le par défaut.
  • trailingSlash dans svelte.config.js accepts 'always', 'never', or 'ignore'. SvelteKit handles le canonical redirection pour vous, mais leaving il misconfigured (surtout 'ignore') peut créer duplicate-contenu variants. Pick un et être consistent.
  • Dynamic routes vous vouloir prerendered besoin an entries function à enumerate le paths à construire temps, or SvelteKit ne va pas know qui URLs à generate.

Choosing an adapter pour le SEO

Le adapter decides comment et où votre SvelteKit app est deployed, et que a SEO consequences (mostly via TTFB, qui feeds LCP):

AdapterRenduSEO implication
adapter-staticComplet SSGVrai static HTML pour chaque page; aucun serveur nécessaire; ideal pour contenu-heavy sites (garder ssr on!)
adapter-nodeSSR on a Node serveurDynamic SSR, complet flexibility; vous exécuter a serveur
adapter-vercelSSR + edgeSSR avec optional edge functions; edge TTFB aide LCP
adapter-cloudflareSSR on WorkersEdge SSR globally — potentially le fastest TTFB/LCP
adapter-netlifySSR + CDNSimilaire profile à Vercel

Pour a blog or docs site, adapter-static avec prerendering donne vous maximum speed et crawlability. Pour dynamic sites, adapter-cloudflare or adapter-vercel put SSR à le edge, qui peut shrink TTFB et aider Plus grand affichage de contenu — mais le adapter seulement picks le deployment shape. Réel TTFB dépend on votre données fetching, mise en cache, et le runtime’s cold-commencer behavior, donc mesurer le deployed page plutôt que assuming le adapter alone delivers le win.

«An adapter is a boundary, not just a deploy target: streaming, the filesystem, caching, edge/runtime APIs, redirects, and error handling can all behave differently between adapters. A route that looks correct with the local dev server or adapter-node isn’t guaranteed to behave identically once deployed through adapter-cloudflare or adapter-vercel — test the production build on the actual target, not just npm run preview. » (Traduction) (Résumé en français de la section quarante-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«## Sitemaps and robots.txt » (Traduction) (Résumé en français de la section quarante-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«SvelteKit has no built-in sitemap or robots.txt — like a headless setup, you build them explicitly. » (Traduction) (Résumé en français de la section quarante-huit, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«- Sitemap, manual: create src/routes/sitemap.xml/+server.js that returns the XML. Add export const prerender = true if you’re on adapter-static. » (Traduction) (Résumé en français de la section quarante-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- Sitemap, dynamic: a server-rendered endpoint that queries your CMS/database and returns fresh XML on each request — best for large or fast-changing sites. » (Traduction) (Résumé en français de la section quarante-neuf, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- Sitemap, packages: svelte-sitemap scans routes post-build (for SSG), and sveltekit-static-sitemap generates from prerendered routes. » (Traduction) (Résumé en français de la section quarante-neuf, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- robots.txt: drop a static file in static/ (served at /robots.txt automatically) or generate it from a src/routes/robots.txt/+server.js endpoint. Whichever you choose, don’t block your .js/.css — Google won’t render from blocked files. » (Traduction) (Résumé en français de la section quarante-neuf, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)

«## Performance and Core Web Vitals » (Traduction) (Résumé en français de la section cinquante, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«SvelteKit’s compiler and framework mechanics give you a structural head start on performance, and Core Web Vitals are a ranking input — but the mechanics themselves don’t guarantee a score. The compiler outputs vanilla JS with no virtual DOM and no runtime library, so a typical SvelteKit page ships less JavaScript than an equivalent React-based app; automatic per-route code splitting, built-in asset and link preloading, file-hashing for long-lived caching, and edge deployment via several adapters are all available. What you build with those mechanics — page weight, image handling, third-party scripts, hydration cost, and the deployment target you actually choose — still decides your measured CWV and your rankings. Treat the framework as removing obstacles, not as delivering the result. The SvelteKit docs point you at the right measurement tools: “Google’s PageSpeed Insights and WebPageTest are excellent ways to understand the performance characteristics of a site.” Image optimization is available via @sveltejs/enhanced-img. » (Traduction) (Résumé en français de la section cinquante et un, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«## AI crawlers and the SSR imperative » (Traduction) (Résumé en français de la section cinquante-deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«Here’s the 2026 wrinkle the older SvelteKit SEO guides miss. Rendering behavior for GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot, and the Bingbot fetch behind Copilot is provider- and version-specific, and current provider documentation doesn’t establish one shared render step you can rely on. Treat “generally fetches static HTML without executing JavaScript” as the safe planning assumption, not a guarantee about every provider forever. A CSR route (bare Svelte, or SvelteKit with ssr: false) ships every one of these crawlers the same empty shell a first-fetch Googlebot request sees; SvelteKit’s default SSR puts your content in the raw HTML so no crawler has to depend on a render step at all. That’s the argument for keeping SSR on for anything you want AI systems to see — not a promise that SSR guarantees inclusion in an AI answer, which depends on factors well beyond rendering. » (Traduction) (Résumé en français de la section cinquante-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Courant SvelteKit SEO mistakes

  • Fetching SEO données dans onMount() au lieu de a serveur charger function — metadata n’est pas dans le initial HTML.
  • Shipping SPA fallback mode (ssr: false) pour contenu vous vouloir ranked.
  • adapter-static avec ssr: false — vide shells, pas prerendered pages.
  • Blocking JS/CSS dans robots.txt — breaks rendu.
  • Skipping trailingSlash configuration — duplicate-contenu variants.
  • En utilisant hash/fragment routing — Googlebot ne peut pas resolve ceux URLs (SvelteKit’s History API par défaut déjà protège vous ici).

Si vous êtes coming à ce depuis le broader framework angle, Svelte/SvelteKit est un de le decoupled frontends a CMS headless pairs avec, et le rendu-mode logic ici est le même logic que governs JavaScript SEO généralement — ceux topics actif alongside ce un dans le cluster.

Ajouter une note d’expert

Épingler une citation d’expert

Nouvelle personne ? Créez son profil non revendiqué à /admin/experts/ → Épingler une citation d’expert d’abord.