prebaked.
Guide

Svelte and SvelteKit SEO

Last reviewed

SvelteKit renders pages on the server by default, so crawlers get finished HTML unless you turn that off. The SEO problems start with SvelteKit's SPA mode, ssr = false, or a plain Svelte app built with Vite: these send an empty shell, and the major AI crawlers do not run the JavaScript that fills it. Fix them with export const prerender = true, by turning SSR back on, or with a prerender service.

At a glance

Setup What crawlers get Fix for AI crawlers Best for
SvelteKit, default (SSR) Finished HTML Nothing to fix Most sites
SvelteKit with export const prerender = true Static HTML built at deploy Nothing to fix for prerendered routes Marketing pages, docs, blogs
SvelteKit with ssr = false or SPA mode (adapter-static fallback) An empty shell Prerender those routes, turn SSR on, or a prerender service Apps behind a login
Svelte + Vite without SvelteKit An empty mount element Move to SvelteKit, prerender, or a prerender service Small apps, widgets

Is Svelte good for SEO?

It depends on how you build it.

  • SvelteKit "employs SSR by default", and its SEO guide says "you should leave it on unless you have a good reason not to." It also normalizes URLs: it "redirects pathnames with trailing slashes to ones without" because "duplicate URLs are bad for SEO."
  • Svelte with Vite is the other official setup: "running npm create vite@latest and selecting the svelte option." The Svelte docs note that "Vite is often used in standalone mode to build single page apps (SPAs)". An SPA renders in the browser.
  • Google renders JavaScript, but queues pages for it, and a page "may stay on this queue for a few seconds, but it can take longer than that."
  • AI crawlers do not render. Vercel and MERJ found that "none of the major AI crawlers currently render JavaScript".

So a default SvelteKit site is in good shape. A Svelte SPA, or a SvelteKit app with SSR turned off, looks empty to ChatGPT, Claude and Perplexity. More on how AI crawlers see your site.

How to check your Svelte app

  1. Run the free checker. It compares your page without JavaScript and in a real browser.

See what ChatGPT sees on your site

  1. Fetch the raw HTML of a deep route.
curl -s https://www.<your-domain>/products | grep -c "<h1"
curl -s https://www.<your-domain>/products | grep -o "<title>.*</title>"

0 headings, or the same title on every route, means the route is rendered in the browser only.

  1. For Google, use the URL Inspection tool in Search Console to see the rendered HTML.

SvelteKit prerender

Prerendering generates a route's HTML at build time. Set it in a page, a server route or the root layout:

// src/routes/+layout.js (whole site) or src/routes/blog/+page.js (one route)
export const prerender = true;

"The prerenderer will start at the root of your app and generate files for any prerenderable pages." With prerender = 'auto', a route is prerendered but stays in the server manifest so it can also be rendered on demand.

Limits from the docs:

  • "Any content that is prerendered will be seen by all users", so personal content cannot be prerendered.
  • "Pages with actions cannot be prerendered."
  • Pages from live data are as fresh as your last build.

adapter-static takes this further: it "will prerender your entire site as a collection of static files." Do not combine it with ssr = false, or the prerendered files are empty shells.

SvelteKit SPA mode and ssr = false

Setting export const ssr = false means the page "renders an empty 'shell' page instead." SPA mode with adapter-static uses a fallback page as the entry point for every route that was not prerendered. The SvelteKit docs are direct about the cost:

  • "This option has large negative performance and SEO impacts."
  • SPA mode "has a large negative performance impact by forcing multiple network round trips" and "harms SEO by often causing sites to be downranked for performance".
  • "You can avoid these drawbacks by prerendering as many pages as possible when using SPA mode (especially your homepage)."

If a route has to stay client-only, keep it to pages that do not need to be found in search, such as an app area behind a login.

Titles and meta tags in Svelte

The SvelteKit SEO guide says "every page should have well-written and unique <title> and <meta name="description"> elements" inside <svelte:head>:

<svelte:head>
  <title>Pricing | Example</title>
  <meta name="description" content="Plans and prices." />
</svelte:head>

A common pattern is to return the SEO data from each page's load function and render it in the root layout. With SSR or prerendering, the tags are in the HTML. In a client-only route, they are written by JavaScript and only crawlers that render see them.

SvelteKit can also serve a sitemap from a server route such as src/routes/sitemap.xml/+server.js. The docs: "Sitemaps help search engines prioritize pages within your site, particularly when you have a large amount of content."

Vite SEO

Vite is often used to build single page apps with React, Vue or Svelte, and a Vite SPA sends crawlers the same empty shell as any client-rendered app. Vite has SSR and prerender APIs, but its SSR guide calls them "a low-level API meant for library and framework authors" and points app developers to higher-level tools first. Its prerender example works "if the routes and the data needed for certain routes are known ahead of time."

In practice, for SEO on a Vite app:

  • Svelte: use SvelteKit, which is "powered by Vite" and renders on the server by default.
  • Vue: see the Vue and Nuxt guide.
  • React: see the React guide.
  • Any existing Vite SPA: a prerender service sends crawlers finished HTML without changing the build.

When a prerender service makes sense for Svelte

A prerender service renders your pages in a real browser when a crawler asks and serves the HTML from a cache. People still get your app. Google calls this dynamic rendering, "a workaround and not a long-term solution", and says that "Googlebot generally doesn't consider dynamic rendering as cloaking." The full explanation is on what is prerendering.

For Svelte, it fits fewer cases than for other frameworks, because SvelteKit already renders on the server. It makes sense when:

  • the app is a Svelte + Vite SPA and moving to SvelteKit is not planned soon,
  • SvelteKit runs in SPA mode on static hosting, and pages from live data cannot be prerendered at build time,
  • routes use ssr = false because of browser-only libraries, and those routes should be found in search.

If your SvelteKit site uses the default SSR, you do not need a prerender service. Check with the free checker first.

When Prebaked is the right choice

  • One snippet: Netlify, Vercel, Cloudflare Worker, nginx or another integration.
  • Same page for bots and people: Prebaked renders your page in Chromium and does not change its content.
  • Never worse than today: if Prebaked is slow or down, crawlers get your original page.
  • Status codes kept: a page that renders as a 404 returns 404, and pages can set their status with <meta name="prerender-status-code" content="404">.
  • Ready signal: set window.prerenderReady = true when the data for a page has loaded.
  • Cache hits are free. You pay for fresh renders only. Warm the cache from your sitemap.

FAQ

Is SvelteKit good for SEO?

Yes. SvelteKit renders on the server by default, normalizes trailing slashes and lets you set titles and descriptions per page in <svelte:head>. Problems appear when SSR is turned off or the app runs in SPA mode.

How do I prerender a page in SvelteKit?

Add export const prerender = true to the page's +page.js or +page.server.js, or to the root +layout.js for the whole site. The page is then built as static HTML at deploy time.

Is SvelteKit SPA mode bad for SEO?

The SvelteKit docs say SPA mode "harms SEO by often causing sites to be downranked for performance", and crawlers that do not run JavaScript see an empty shell. Prerender as many pages as you can, or use a prerender service for the rest.

Is Vite good for SEO?

Vite is a build tool. A Vite single page app renders in the browser, so AI crawlers see an empty page. Use a framework on top of Vite that renders on the server or at build time, or a prerender service.

Do I need a prerender service for SvelteKit?

Usually not. With the default SSR, crawlers already get finished HTML. A prerender service helps Svelte SPAs, SvelteKit apps in SPA mode and routes with ssr = false.