Back to Blog
Tutorial9 min read2026-07-03

How to Deploy a SvelteKit Static Site

Turn your SvelteKit app into a fully static site with adapter-static and prerendering. Learn how to configure, build, and deploy it to a global CDN with automatic SSL.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

Not every SvelteKit app needs a server. If your content is known at build time — a blog, docs, a marketing site, a portfolio — you can prerender the whole thing to static HTML and serve it from a CDN. That's faster, cheaper, and infinitely scalable. This guide covers deploying a SvelteKit app as a static site with adapter-static.

When static is the right choice

Use adapter-static when:

  • All pages can be prerendered at build time.
  • You don't need per-request server logic (form actions, server-side auth, dynamic API routes that must run on the server).
  • You want CDN distribution and zero server cost.

If you need server endpoints or per-request SSR, use a Node adapter instead. For everything else, static wins.

Installing the static adapter

npm install -D @sveltejs/adapter-static

Configure it in svelte.config.js:

import adapter from '@sveltejs/adapter-static';

export default {
  kit: {
    adapter: adapter({
      pages: 'build',
      assets: 'build',
      fallback: undefined,   // set to '200.html' for SPA fallback
      precompress: true,
    }),
  },
};

Enabling prerendering

Tell SvelteKit to prerender. The simplest approach is a root layout that opts everything in:

// src/routes/+layout.js
export const prerender = true;

With prerender = true at the root, SvelteKit crawls your app from the entry point, follows links, and generates static HTML for every reachable page. Any route that can't be prerendered (e.g. it reads request headers) will throw at build time, which is a useful guardrail.

Dynamic routes

For dynamic routes like /blog/[slug], give SvelteKit the list of slugs to prerender via entries:

// src/routes/blog/[slug]/+page.js
export const prerender = true;

export function entries() {
  return [
    { slug: 'first-post' },
    { slug: 'second-post' },
  ];
}

Or return the slugs from your content source (a CMS, a folder of markdown) so the list stays in sync automatically.

SPA fallback

If parts of your app are client-rendered and use dynamic routes that can't be enumerated, set a fallback so the CDN serves a single HTML shell for unmatched paths:

adapter({ fallback: '200.html' })

This turns your build into a hybrid: prerendered pages where possible, client-side routing for the rest. Note this disables the build-time guarantee that every route resolves — use it deliberately.

Building

npm run build

The output lands in build/ — plain HTML, CSS, JS, and assets. No server, no node_modules needed at runtime. With precompress: true, you also get .gz and .br variants so the CDN can serve pre-compressed responses.

Deploying to a static host

Static SvelteKit deploys are trivial because there's nothing to run — just files to serve. On PandaStack you deploy it as a static site: the platform auto-detects SvelteKit, runs npm run build, and serves the build/ output from a global CDN. Static builds run in fast microVMs, and your site gets a custom domain with automatic SSL.

The key settings the platform infers (and you can override):

SettingValue
Install commandnpm ci (overridable: yarn/pnpm/bun)
Build commandnpm run build
Output directorybuild

Caching and immutable assets

SvelteKit fingerprints its JS/CSS filenames with content hashes, so those assets are safely cacheable forever. HTML should be revalidated on each request so new deploys appear immediately. A good CDN config caches hashed assets with immutable, max-age=31536000 and serves HTML with a short or revalidating cache. Most static hosts (PandaStack included) apply sensible defaults automatically.

Environment variables at build time

Static sites can only use env vars available at build time, and only PUBLIC_-prefixed vars are exposed to the client bundle:

import { PUBLIC_API_BASE } from '$env/static/public';

There's no server to read secrets at runtime, so never put secrets in a static build — anything in the bundle is public.

Deploying

Push your repo and connect it as a static site. The platform installs, builds, and publishes to the CDN. Live build logs show prerender progress and surface any route that failed to prerender.

git push origin main

Conclusion

SvelteKit's adapter-static plus prerender = true turns your app into pure static files: enumerate dynamic routes with entries(), optionally add an SPA fallback, and deploy the build/ output to a CDN. It's the cheapest, fastest, most scalable way to ship content sites.

Try it on PandaStack's free tier, which includes static sites with custom domains and automatic SSL — connect your SvelteKit repo at [dashboard.pandastack.io](https://dashboard.pandastack.io) and it builds and publishes to the CDN with one push.

References

  • [SvelteKit: adapter-static](https://svelte.dev/docs/kit/adapter-static)
  • [SvelteKit: Prerendering](https://svelte.dev/docs/kit/page-options#prerender)
  • [SvelteKit: Single-page apps (SPA fallback)](https://svelte.dev/docs/kit/single-page-apps)
  • [SvelteKit: Environment Variables](https://svelte.dev/docs/kit/$env-static-public)
  • [MDN: HTTP Caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching)

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also