Deploy SvelteKit
deploybase supports SvelteKit with adapter-static, in two shapes: a fully prerendered static site, or a single-page app that routes in the browser. Server-side rendering and form actions are not supported: the output is static. For server code next to the site, use functions (HTTPS calls in beta on paid plans); a SvelteKit adapter for them does not exist yet.
Build defaults
Section titled “Build defaults”| Setting | Value |
|---|---|
| Build command | npm run build |
| Output directory | build |
| Image | node:24-alpine |
Every value is editable per project, and the full defaults table covers the other frameworks.
Install the adapter
Section titled “Install the adapter”npm install -D @sveltejs/adapter-staticSvelteKit 2 or later. Then pick which of the two shapes your app is.
Which one are you building?
Section titled “Which one are you building?”| What you are building | Use |
|---|---|
| Marketing site, docs, blog, portfolio | Prerendered static site |
| App with client-side routing or dynamic routes you cannot list at build time | Single-page app |
Both paths use adapter-static and both deploy the same way. Only svelte.config.js and your root layout differ.
Prerendered static site
Section titled “Prerendered static site”Every route is written to its own HTML file at build time, so each URL is served as real HTML. This is the better choice for content sites: search engines and social previews get a full page without running JavaScript.
svelte.config.js:
import adapter from '@sveltejs/adapter-static';
/** @type {import('@sveltejs/kit').Config} */const config = { kit: { adapter: adapter({ pages: 'build', assets: 'build', fallback: undefined, precompress: false, strict: true, }), },};
export default config;src/routes/+layout.js:
export const prerender = true;Every route has to be prerenderable. For dynamic routes that SvelteKit cannot find by crawling links, export an entries function from the corresponding +page.js.
Single-page app
Section titled “Single-page app”SPA mode emits one app shell, 200.html, and lets the SvelteKit router resolve URLs in the browser. Use it when routes depend on data that only exists at runtime, such as a dashboard behind a login.
svelte.config.js:
import adapter from '@sveltejs/adapter-static';
/** @type {import('@sveltejs/kit').Config} */const config = { kit: { adapter: adapter({ pages: 'build', assets: 'build', fallback: '200.html', precompress: false, strict: false, }), },};
export default config;src/routes/+layout.js:
export const ssr = false;You do not need export const prerender = true in SPA mode, and you do not need to enumerate dynamic routes.
The fallback: '200.html' above is the only thing you need: deploybase picks that file up on its own and serves it for any path with no matching file, so deep links and hard reloads land in your app. See SPA fallback and custom 404 pages for the full detection rules and the _redirects alternative.
Mixing prerendering and SPA mode is fine: routes you mark prerender = true are still written as their own HTML files, and the fallback only covers what is left over.
When it breaks
Section titled “When it breaks”Build fails with “adapter-static requires prerender”: adapter-static needs to know what to write to disk, and one of your routes cannot be prerendered. There are two ways forward.
- Prerender everything. Add
export const prerender = true;tosrc/routes/+layout.jsand exportentriesfor any dynamic route SvelteKit cannot reach by crawling. Best for content sites. - Switch to SPA mode. Set
fallback: '200.html'in the adapter options andexport const ssr = false;in your root+layout.js. Routes resolve in the browser, and deploybase serves200.htmlfor paths with no matching file.
Setting strict: false on its own also silences the build error, but any route left unrendered has no file behind it. Without a 200.html (or a _redirects catch-all) in the build output, those URLs fall through to your 404 page.
Deep links 404 in a SPA: check that build/200.html exists in the build output. If your adapter config sets fallback to something else, such as index.html, rename it to 200.html or add a _redirects file with /* /index.html 200.
Using bun instead of npm: bun is supported natively. If your repository has a bun.lock or bun.lockb committed, deploybase detects it and installs with bun automatically. To set it explicitly:
curl -X PATCH "https://api.deploybase.eu/api/v1/projects/$PROJECT_ID" \ -H "Authorization: Bearer $DEPLOYBASE_API_KEY" \ -H "Content-Type: application/json" \ -d '{"package_manager": "bun"}'The build command stays npm run build, which runs the build script from your package.json against the dependencies bun installed. See the build system for the full package-manager reference.
Live a8b7eb1d built