full-stack-skills/svelte-skills

sveltekit-config

SvelteKit 配置/构建/部署/性能技能。当用户配置 adapter(node/static/cloudflare/netlify/vercel)、使用 advanced routing/layouts、优化性能(代码分割/asset/hydration)、处理 images(@sveltejs/enhanced-img)、实现 accessibility/SEO、调试 SvelteKit 应用、从 SvelteKit v1/Sapper 迁移时使用。

Ver código-fonte

Como usar

  1. Copie o comando e verifique o pacote antes de instalar no seu ambiente de agente.
  2. Consulte no original as ferramentas, credenciais e ambientes necessários.
  3. Descreva os dados de entrada e a entrega esperada; confira a saída com as fontes.
npx skills add https://github.com/full-stack-skills/svelte-skills --skill sveltekit-config

Antes de começar

  • A instalação não inclui assinatura de modelo, franquia API ou acesso aos seus arquivos.
  • Estrelas e instalações indicam atividade, não um teste independente de qualidade ou segurança.
Documento original do Skill

Renderizado do repositório de origem, preservando títulos, exemplos, código, tabelas, links e imagens.

SvelteKit Config

When to use this skill

Use this skill whenever you are working on SvelteKit's configuration, build pipeline, deployment, performance, images, accessibility, SEO, debugging, or migration concerns. This includes:

  • Choosing or configuring an adapter (adapter-node, adapter-static, adapter-cloudflare, adapter-netlify, adapter-vercel)
  • Building (vite build) and previewing (vite preview) production apps
  • Advanced routing (rest params, optional params, matchers, route sorting, filename encoding)
  • Advanced layouts (route groups, breaking out of layouts with @)
  • Auth integration patterns (sessions vs tokens, hooks-based auth)
  • Performance optimization (code splitting, asset opt, avoiding waterfalls)
  • Image handling (@sveltejs/enhanced-img, CDN loading, <picture>/<img> patterns)
  • Accessibility (route announcements, focus management, lang attribute)
  • SEO (titles, meta tags, sitemaps, JSON-LD)
  • Breakpoint debugging (VS Code, Chrome DevTools)
  • Migrating from SvelteKit v1 or Sapper

For routing/data/load basics, see sveltekit-overview. For Svelte components/runes, see svelte-runes.

Critical: Building and previewing

vite build runs in two stages: Vite produces an optimized production build, then your adapter tailors the output for the target platform. Prerendering executes during build.

During the build, SvelteKit loads your +page/layout(.server).js for analysis. Code that must NOT run at build time should guard with building from $app/environment:

js
import { building } from '$app/environment';
import { initialiseDatabase } from '$lib/server/database';

if (!building) initialiseDatabase();

export function load() { /* ... */ }

After building, run vite preview (or npm run preview) to test the production build locally. Preview runs in Node, so adapter-specific behavior (e.g. Cloudflare's platform object) does NOT apply — use wrangler dev for Cloudflare or the platform's CLI for accurate testing.

sh
npm run build       # vite build + adapter
npm run preview     # vite preview (Node)

Critical: Adapters — when to use which

The adapter is configured in svelte.config.js under kit.adapter. adapter-auto ships by default in new projects and picks the right adapter for known deployment environments (Cloudflare Pages, Netlify, Vercel, Azure SWA, SST, Google Cloud Run). Once you've chosen a target, install that adapter explicitly so it lands in your lockfile.

TargetAdapterNotes
Node server / Docker / VM@sveltejs/adapter-nodeStandalone Node server. Most flexible.
Static hosting (no SSR)@sveltejs/adapter-staticSSG or SPA fallback.
Cloudflare Workers / Pages@sveltejs/adapter-cloudflareUnified adapter for both.
Netlify@sveltejs/adapter-netlifyNode functions or Deno edge.
Vercel@sveltejs/adapter-vercelServerless or edge, ISR support.

Adapter quick guide:

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

Platform-specific context

Some adapters expose platform info (KV namespaces, Durable Objects, env vars) via event.platform in hooks/server routes. Type augmentation in src/app.d.ts:

ts
declare global {
  namespace App {
    interface Platform {
      env: { MY_KV: KVNamespace };
    }
  }
}
export {};

Always prefer $env/static/private for environment variables — $env/dynamic/* cannot be used during prerendering.

Critical: Advanced routing

SvelteKit routes are filesystem-based. Beyond basic dynamic segments, you have several advanced features.

Rest parameters — [...rest]

Match an unknown number of segments. src/routes/a/[...rest]/z/+page.svelte matches /a/z, /a/b/z, /a/b/c/z. The rest param is a string with /-separated segments.

tree
src/routes/[org]/[repo]/tree/[branch]/[...file]/+page.svelte

Use rest parameters to render custom 404s — add [...path]/+page.js that calls error(404) so a nested +error.svelte is reached.

Optional parameters — [[lang]]

Wrap with double brackets to make a param optional. [[lang]]/home matches both /home and /en/home. An optional param cannot follow a rest param.

Matching — [name=type]

Constrain a parameter with a matcher from src/params/:

js
// src/params/fruit.js
/** @type {import('@sveltejs/kit').ParamMatcher} */
export function match(param) {
  return param === 'apple' || param === 'orange';
}

Then write src/routes/fruits/[page=fruit]/+page.svelte. Matchers run on both server and browser.

Sorting

When multiple routes match, SvelteKit sorts by:

  1. More specific routes win (fewer params = more specific)
  2. Matchers ([name=type]) beat unconstrained ([name])
  3. [[optional]] and [...rest] are lowest priority unless they're the final segment
  4. Ties resolved alphabetically

Encoding special characters

Use hex escape [x+nn] in folder names: / → [x+2f], : → [x+3a], etc. Use [u+nnnn] for Unicode (no surrogate pairs needed).

tree
src/routes/smileys/[x+3a]-[x+29]/+page.svelte
# matches /smileys/:-)

Critical: Advanced layouts

By default, the layout hierarchy mirrors the folder hierarchy. Use these patterns to reshape it.

Route groups — (group)

Parentheses-wrapped folder names don't appear in the URL. Use to share a layout between routes without affecting URL structure.

tree
src/routes/
├ (app)/dashboard/+page.svelte
├ (app)/+layout.svelte          # app shell
├ (marketing)/about/+page.svelte
├ (marketing)/+layout.svelte    # marketing shell
└ +layout.svelte

Breaking out — +page@layout.svelte

Append @<segment> (or @ for root) to reset the layout chain. +page@(app).svelte inherits only from (app)/+layout.svelte.

Options: +page@[id].svelte, +page@item.svelte, +page@(app).svelte, +page@.svelte.

Layouts can also break out: +layout@.svelte rewinds to root for everything below it.

Reset to root

If you want most of your app under one layout but a few routes to escape, put everything inside a group except the outliers:

tree
src/routes/
├ (app)/...
└ admin/+page.svelte   # does NOT inherit (app) layout

Critical: Auth integration

Auth = authentication (who is this?) + authorization (what can they do?).

Sessions vs tokens

  • Sessions: ID stored in DB. Revocable instantly, requires DB lookup per request.
  • JWT tokens: Self-contained, no DB lookup, but cannot be revoked immediately. Better latency.

Integration pattern

Check auth cookies in src/hooks.server.js, populate event.locals.user, then read locals in +page.server.js / +server.js load functions.

js
// src/hooks.server.js
export async function handle({ event, resolve }) {
  event.locals.user = await getUser(event.cookies.get('session'));
  return resolve(event);
}

Libraries

  • npx sv add better-auth — Better Auth integration via Svelte CLI
  • Lucia auth guide — reference SvelteKit examples for session-based auth

Always require path: '/' when calling cookies.set(...) in SvelteKit v2.

Critical: Performance optimization

SvelteKit ships with: code-splitting, asset preloading, file hashing, request coalescing, parallel loading, data inlining, conservative invalidation, link preloading. To go further:

Diagnose

  • PageSpeed Insights / Lighthouse / WebPageTest
  • Chrome DevTools Network + Performance tabs
  • Test in preview mode (after vite build), not dev mode

Assets

  • Use @sveltejs/enhanced-img for images (smaller formats, intrinsic dimensions)
  • Lazy-load below-the-fold videos with preload="none"
  • Subset fonts; preload critical fonts via handle hook's preload filter

Code size

  • Use Svelte 5 (smaller than 4)
  • Use rollup-plugin-visualizer to find heavy packages
  • Prefer dynamic import() for conditional code
  • Push third-party scripts to web workers (Partytown)

Avoid waterfalls

  • Use server `load` functions for backend calls (avoid client → server → backend chains)
  • Issue parallel queries with Promise.all / DB joins
  • SPA mode causes waterfalls — prerender instead

Hosting

  • Deploy frontend near backend (or use edge)
  • Ensure HTTP/2+

Critical: Images

Vite's built-in handling

svelte
<script>
  import logo from '$lib/assets/logo.png';
</script>
<img alt="logo" src={logo} />

Vite hashes the filename and inlines small assets.

@sveltejs/enhanced-img

Build-time image optimization: generates avif/webp, sets intrinsic width/height (prevents CLS), strips EXIF.

js
// vite.config.js — plugin order matters
import { enhancedImages } from '@sveltejs/enhanced-img';
import { sveltekit } from '@sveltejs/kit/vite';
export default { plugins: [enhancedImages(), sveltekit()] };

Usage:

svelte
<enhanced:img src="./image.jpg" alt="..." sizes="min(1280px, 100vw)" />

Generated <picture> includes multiple formats and sizes for HiDPI. Provide 2x source for retina displays.

Custom widths: <enhanced:img src="./image.png?w=1280;640;400" /> Per-image transforms: <enhanced:img src="./image.jpg?blur=15" />

Dynamic CDN loading

For images unavailable at build time (CMS, DB), use a CDN library:

  • @unpic/svelte — CDN-agnostic
  • svelte-cloudinary — Cloudinary
  • CMS-bundled: Contentful, Storyblok, Contentstack

Best practices

  • Set fetchpriority="high" and avoid loading="lazy" for LCP images
  • Always provide alt text
  • Don't use em/rem in sizes
  • Mix strategies: Vite for <meta>, enhanced-img for hero, CDN for user content

Critical: Accessibility

SvelteKit provides an accessible foundation; you're still responsible for app-level a11y.

Route announcements

SvelteKit injects a live region that reads the <title> after each client-side navigation. Every page must have a unique, descriptive <title> in a <svelte:head>:

svelte
<svelte:head>
  <title>Todo List</title>
</svelte:head>

Focus management

After each navigation, SvelteKit focuses <body> (or [autofocus] element if present). Override with afterNavigate for custom behavior:

js
import { afterNavigate } from '$app/navigation';
afterNavigate(() => document.querySelector('.focus-me')?.focus());

Use data-sveltekit-keepfocus on a <form> to preserve input focus. goto(url, { keepFocus: true }) for programmatic nav.

lang attribute

Set <html lang="en"> (or your language) in src/app.html. For multi-language sites, use a transformPageChunk in handle to set per-request.

Critical: SEO

SvelteKit ships with SSR, normalized trailing-slash URLs, and good defaults. Manual steps:

Per-page meta

svelte
<svelte:head>
  <title>Page Title — Site Name</title>
  <meta name="description" content="..." />
  <meta property="og:title" content="..." />
  <meta property="og:description" content="..." />
  <meta property="og:image" content="..." />
  <meta property="og:type" content="website" />
  <link rel="canonical" href="https://..." />
</svelte:head>

Common pattern: return SEO data from load, render in root layout's <svelte:head>.

Sitemap

js
// src/routes/sitemap.xml/+server.js
export async function GET() {
  return new Response(`<?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      <!-- <url> entries -->
    </urlset>`, { headers: { 'Content-Type': 'application/xml' } });
}

JSON-LD structured data

Inject via <svelte:head> with <script type="application/ld+json">.

Critical: Migration

SvelteKit v1 → v2

Use npx sv migrate sveltekit-2 (or npx svelte-migrate for older projects). Breaking changes:

  • error(...) and redirect(...) are no longer thrown — just call them
  • cookies.set/delete/serialize requires path: '/'
  • Top-level promises in load are NOT awaited automatically — use await explicitly
  • goto no longer accepts external URLs (use window.location.href)
  • paths are now consistently relative (default true)
  • $app/stores deprecated in 2.12 — migrate to $app/state (Svelte 5 runes)
  • Svelte 4 required, Node 18.13+
  • vitePreprocess must be imported from @sveltejs/vite-plugin-svelte

Sapper → SvelteKit

  • package.json: add "type": "module", remove polka/sapper/sirv/compression
  • Add @sveltejs/kit + an adapter
  • Scripts: sapper build → vite build, sapper dev → vite dev, node __sapper__/build → node build
  • src/template.html → src/app.html (replace %sapper.* placeholders)
  • Routes: routes/about/index.svelte → routes/about/+page.svelte
  • _layout.svelte → +layout.svelte, _error.svelte → +error.svelte
  • preload → load (different API: single event arg, no this.fetch)
  • stores / navigating from $app/stores (or $app/state in 2.12+)
  • Regex routes → matchers in src/params/
  • sapper:prefetch → data-sveltekit-preload-data
  • sapper:noscroll → data-sveltekit-noscroll
  • Move internal libs from src/node_modules/... to src/lib

Critical: Debugging

VS Code

Built-in debug terminal works out of the box:

  1. CMD/Ctrl+Shift+P → "Debug: JavaScript Debug Terminal"
  2. Run npm run dev in that terminal
  3. Set breakpoints, hit them in the browser

Or create .vscode/launch.json:

json
{
  "version": "0.2.0",
  "configurations": [
    { "command": "npm run dev", "name": "dev", "request": "launch", "type": "node-terminal" }
  ]
}

Chrome DevTools / Edge

sh
NODE_OPTIONS="--inspect" npm run dev

Open the site, then click the "Open dedicated DevTools for Node.js" icon (Node logo, top-left). Or visit chrome://inspect.

Quick Fixes

  • `building` flag: Wrap one-time init code in if (!building) to prevent it running during vite build.
  • `fallback` in `adapter-static`: Use 200.html for SPA mode, but avoid index.html (conflicts with prerendered /).
  • GitHub Pages: Set paths.base to repo name and fallback: '404.html'. Add .nojekyll to static/.
  • Node origin: Set ORIGIN env var if you're behind a proxy and see "Cross-site POST form submissions are forbidden".
  • XFF depth: Behind N proxies, set XFF_DEPTH=N so getClientAddress() returns the real client IP.
  • Compression: Use @polka/compression not compression — SvelteKit streams responses.
  • `.env` in production: Production doesn't auto-load .env. Use node --env-file=.env build (Node 20.6+) or -r dotenv/config.
  • `platform` only in dev/preview: Test Cloudflare/Netlify/Vercel platform APIs with their respective CLIs (wrangler dev, netlify dev, vercel dev).
  • `fs` not available: Use read from $app/server (works in edge by fetching from deployed assets).
  • `goto` external URL: Use window.location.href instead.
  • Cookie path: SvelteKit v2 requires path: '/' on cookies.set(...).
  • Trailing slash: Set trailingSlash: 'always' if your host doesn't serve /a.html from /a.

Gotchas

  • Preview is not production: vite preview runs in Node, doesn't emulate adapter-specific behavior. Use the platform's CLI for accurate local testing.
  • `adapter-auto` is just for zero-config: Once you've decided on a target, install the real adapter so it lands in the lockfile and you can pass options.
  • Server bundle size on Cloudflare: Workers have a size limit. Move large libraries to client-only imports if you hit it.
  • AWS / Node 18: SvelteKit v2 requires Node 18.13+. Older Node versions fail with cryptic errors.
  • ISR + prerender: ISR has no effect on routes with export const prerender = true.
  • `adapter-cloudflare-workers` deprecated: Use @sveltejs/adapter-cloudflare (with assets.directory + assets.binding in wrangler config).
  • Svelte 4 → 5: $app/stores is deprecated; use $app/state. Update Svelte first, then SvelteKit.
  • Tailwind + `<enhanced:img>`: Tag-name selectors need enhanced\:img to escape the colon.
  • Match `data-sveltekit-noscroll` for chat/SPA-like UIs: Default scroll-to-top behavior can break infinite-scroll apps.
  • Vite asset inlining: Assets below assetsInlineLimit (default ~4kb) get base64-inlined. Excludes svg for enhanced-img.

FAQ

Should I use `adapter-auto`? Yes for prototyping. Once you've chosen a target, swap to the specific adapter so you can configure it.

SPA mode vs full SSR? Full SSR with adapter-static (prerender) is best for SEO/perf. SPA fallback is for when you must deploy to static-only hosting without prerendering everything. SPA hurts SEO and performance.

When should I prerender? Pages that return the same content for every visitor (marketing pages, blog posts, docs). Add export const prerender = true to the route.

How do I know which adapter is being used in production? adapter-auto logs at build time which one it picked. Otherwise, check svelte.config.js.

Can I use the same `svelte.config.js` for multiple adapters? No — you must run vite build once per adapter. Common CI pattern: build matrix per target.

Why is my Cloudflare Worker huge? Bundle bloat — server-side imports pull in large deps. Move them to dynamic import() or client-only.

Do I need Svelte 5 for SvelteKit 2? You need Svelte 4+. Svelte 5 is recommended for $app/state and runes.

Examples & References

Examples

FileWhat it covers
examples/build-preview.mdvite build, vite preview, env vars at build time
examples/adapter-node.mddev/build/deploy, custom server, env vars
examples/adapter-static.mdprerender all, SPA fallback, GitHub Pages
examples/adapter-cloudflare.mdworkers, pages, runtime APIs, env vars
examples/adapter-netlify.mddeploy, edge functions, env vars
examples/adapter-vercel.mddeploy, image opt, ISR, env vars, skew protection
examples/writing-adapter.mdcustom adapter using the builder API
examples/advanced-routing.mdrest params, optional, matchers, sort, encoding
examples/advanced-layouts.mdnested layouts, named layouts, error reset, groups
examples/performance.mdcode splitting, asset opt, hydration opt
examples/images.mdenhanced-img, dynamic CDN loading, best practices
examples/accessibility.mdroute announcements, focus management, lang attribute
examples/seo.mdmeta tags, OG tags, JSON-LD, sitemaps
examples/debugging.mdVS Code launch.json, browser breakpoints
examples/migration-v2.mderror/redirect changes, cookie path, top-level promises

References

FileWhat it covers
references/adapters-comparison.mddetailed when-to-use-each-adapter matrix
references/building-reference.mdvite build options, preview, env vars
references/routing-advanced-reference.mdrest/optional/matchers/sort/encoding deep-dive
references/layouts-advanced-reference.mdnested/named/groups, reset, breaking out
references/auth-reference.mdsessions vs tokens, integration points, libs
references/performance-reference.mdfull optimization checklist
references/images-reference.mdVite + @sveltejs/enhanced-img reference
references/a11y-reference.mdaccessibility patterns and resources
references/seo-reference.mdSEO setup, meta tags, structured data
references/migration-v1-v2-reference.mdfull breaking-changes list
references/migration-sapper-reference.mdcomplete Sapper → SvelteKit migration
references/debugging-reference.mdIDE/debugger configs
do mesmo repositório

Mais Skills

Todos os Skills