Skip to content
Back to Stack Recommender

SvelteKit for SSG and SSR

SvelteKit with adaptive rendering (SSG/SSR/SPA per page), Svelte 5 runes, and zero-runtime CSS.

Static SitesSimple

Stack Components

FrameworkSvelteKit 2 + Svelte 5
RenderingAdaptive (SSG/SSR/SPA)
StylingSvelte scoped CSS
DataSvelteKit load functions
DeployAdapter-static / Adapter-node

Why

Svelte compiles to vanilla JS — no virtual DOM, 10x smaller bundles than React. SvelteKit lets each page choose SSG (blog), SSR (dashboard), or SPA (admin) via one config.

Runes ($state, $derived) make reactivity explicit and debuggable.

When

Choose SvelteKit for content + app hybrids (blog + dashboard in one site), performance-critical landing pages, and small teams wanting minimal JS. Avoid for design systems (React ecosystem larger) or massive SPAs.

How

1. Scaffold — npm create svelte@latest myapp, choose "SvelteKit minimal" 2. Svelte 5 runes — $state, $derived, $effect replace let/export let 3. Load functions — +page.ts export async function load({ fetch }) for data 4. Adaptive rendering — export const prerender = true in +page.ts for SSG 5. Layouts — +layout.svelte for shared nav, +layout.ts for shared load 6. Forms — form actions in +page.server.ts, use:enhance for progressive enhancement 7. Static export — adapter-static with prerender entries, fallback: 'spa' option 8. Deploy — npm run build, output to Netlify/Vercel/Cloudflare/GitHub Pages

Example

// src/routes/blog/[slug]/+page.ts — load function (SSG) import type { PageLoad } from "./$types"; export const prerender = true; // generate at build time export const load: PageLoad = async ({ params, fetch }) => { const post = await fetch(`/api/posts/${params.slug}`).then((r) => r.json()); return { post }; }; // src/routes/blog/[slug]/+page.svelte — Svelte 5 runes <script lang="ts"> let { data } = $props(); let liked = $state(false); let label = $derived(liked ? "Liked ❤" : "Like"); </script> <h1>{data.post.title}</h1> <article>{@html data.post.content}</article> <button onclick={() => (liked = !liked)}>{label}</button> <style> /* Scoped CSS — zero runtime, compiled to single class */ h1 { color: #1a1a1a; } button { padding: 0.5rem 1rem; border-radius: 0.5rem; } </style> // src/routes/admin/+page.ts — SPA (client-only) export const prerender = false; export const ssr = false; // pure SPA page // svelte.config.js — adaptive static export import adapter from "@sveltejs/adapter-static"; export default { kit: { adapter: adapter({ fallback: "index.html" }), // SPA fallback prerender: { entries: ["*"] }, }, };

Common Problems

  • ⚠prerender + dynamic data — build fails if load uses request.url, use params only
  • ⚠Runes in .svelte only — $state in .ts file errors, use stores for shared state
  • ⚠adapter-static needs all routes prerendered — set fallback for SPA routes
  • ⚠Form action redirect — must use throw redirect(303, '/path'), not return

Best Practices

  • ✓Use runes ($state/$derived) — explicit reactivity, better DevTools, no magic
  • ✓Adaptive rendering per page — prerender blog, SSR dashboard, SPA admin in one app
  • ✓Form actions over API routes — type-safe, CSRF-protected, progressive enhancement
  • ✓Scoped CSS over global — compiled away, no runtime, no naming collisions

FAQ

What is SvelteKit for SSG and SSR and what projects is it for?

SvelteKit with adaptive rendering (SSG/SSR/SPA per page), Svelte 5 runes, and zero-runtime CSS. It pairs layered technologies for end-to-end type safety and out-of-the-box deploys, fitting everything from MVPs to production SaaS.

How do I spin up a working demo with SvelteKit for SSG and SSR in 10 minutes?

Two steps: (1) Scaffold — npm create svelte@latest myapp, choose "SvelteKit minimal"; (2) Svelte 5 runes — $state, $derived, $effect replace let/export let. Get the local dev server running, then wire one real data source to verify the end-to-end loop.

What is the most common pitfall with SvelteKit for SSG and SSR and how do I avoid it?

The most common pitfall is: prerender + dynamic data — build fails if load uses request.url, use params only. Avoid it by adding the matching checklist to your PR template and running type-check + lint + unit tests in CI — three gates before merge.

What are the best practices for SvelteKit for SSG and SSR?

Best practices for SvelteKit for SSG and SSR include: Use runes ($state/$derived) — explicit reactivity, better DevTools, no magic; Adaptive rendering per page — prerender blog, SSR dashboard, SPA admin in one app; Form actions over API routes — type-safe, CSRF-protected, progressive enhancement. The first one — "Use runes ($state/$derived) — explicit reactivity, better DevTools, no magic" — should be set up at project init to avoid costly rework later.

When should I NOT choose SvelteKit for SSG and SSR?

Pick something else in three cases: (1) the team has zero experience with the core framework and the deadline is tight (learning-curve risk); (2) it's a pure content/marketing site (Astro is lighter); (3) you need very high throughput (>10k RPS) or strict-consistency microservices (Go/Rust). SvelteKit for SSG and SSR shines for mid-to-high complexity full-stack and API work — don't over-engineer simple static pages with it.