Back to Blog
Tutorial9 min read2026-07-05

How to Deploy SvelteKit to Production

SvelteKit's adapters decide everything about how you deploy. Learn when to use adapter-node vs adapter-static, how to containerize the Node build, and how to ship it to production.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

SvelteKit is a meta-framework, which means how you deploy it depends entirely on which adapter you choose. Pick the wrong one and you'll fight your hosting platform forever. This guide explains the adapter model and walks through a production Node deployment.

Adapters: the one decision that matters

SvelteKit builds against an adapter that targets a specific environment:

AdapterOutputUse when
adapter-staticPre-rendered HTML/CSS/JSFully static site, no server-side logic
adapter-nodeA Node.js serverYou need SSR, form actions, API routes
adapter-autoDetects common hostsConvenient but opaque; pin a real adapter for control

If your app has +page.server.ts files, form actions, or +server.ts API endpoints that run per-request, you need a server — use adapter-node. If everything can be pre-rendered, adapter-static gives you a free, blazing-fast static deploy.

Option A: Static deployment

For a content site or marketing pages, prerender everything:

// svelte.config.js
import adapter from '@sveltejs/adapter-static';

export default {
  kit: {
    adapter: adapter({
      pages: 'build',
      assets: 'build',
      fallback: '200.html', // for SPA-style routing
    }),
  },
};

Add export const prerender = true; in your root layout. Then npm run build produces a build/ directory of plain files. Host it anywhere that serves static assets — including PandaStack static sites, which build in microVMs and serve over the global edge for free.

Option B: Node server deployment

For SSR apps, use adapter-node:

// svelte.config.js
import adapter from '@sveltejs/adapter-node';

export default {
  kit: { adapter: adapter() },
};

This produces build/index.js — a standalone Node server. Containerize it:

FROM node:20-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
RUN npm prune --production

FROM node:20-slim
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/build ./build
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/package.json ./
EXPOSE 3000
CMD ["node", "build"]

The adapter-node server reads PORT and HOST from the environment. Set HOST=0.0.0.0 so it accepts external connections inside the container, and bind PORT to whatever your platform assigns.

Environment variables: public vs private

SvelteKit splits env vars by visibility:

  • $env/static/private and $env/dynamic/private — server-only secrets (API keys, DATABASE_URL).
  • $env/static/public and $env/dynamic/public — prefixed PUBLIC_, shipped to the browser.
import { DATABASE_URL } from '$env/static/private';
import { PUBLIC_API_BASE } from '$env/static/public';

Never put a secret behind PUBLIC_ — it ends up in your client bundle. This trips up a lot of teams.

Deploying on PandaStack

PandaStack handles both adapter paths:

  • Static SvelteKit (adapter-static) — deploy as a static site. PandaStack auto-detects the framework, runs npm run build, and serves the output globally. Unlimited static sites on Pro and above; the free tier includes 5.
  • SSR SvelteKit (adapter-node) — deploy as a container app. PandaStack detects Node, builds via rootless BuildKit, and runs node build. Add a managed database and DATABASE_URL is injected automatically.

Either way you get automatic SSL on custom domains, live build logs, and rollbacks from deploy history.

Production checklist

  • Pick a real adapter, not adapter-auto, for predictable behavior.
  • Set HOST=0.0.0.0 for containerized Node builds.
  • Audit PUBLIC_ env vars — no secrets in the client bundle.
  • Prerender what you can even in an SSR app (export const prerender = true per route) to cut server load.
  • Compress responses — adapter-node doesn't gzip by default; let your ingress/proxy handle it.

References

  • SvelteKit adapters overview: https://svelte.dev/docs/kit/adapters
  • adapter-node docs: https://svelte.dev/docs/kit/adapter-node
  • adapter-static docs: https://svelte.dev/docs/kit/adapter-static
  • SvelteKit environment variables: https://svelte.dev/docs/kit/$env-static-private
  • Prerendering in SvelteKit: https://svelte.dev/docs/kit/page-options#prerender

---

Whether your SvelteKit app is fully static or server-rendered, PandaStack's free tier covers both — static sites and container apps with automatic SSL and a managed database on tap. Deploy at https://dashboard.pandastack.io

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also