Skip to main content
The Xano Engine and every ephemeral have a static host. --static <dir> on a deploy publishes a built frontend there after the backend import, and xanosdk publish republishes one without touching the backend.

Publish with a deploy

Point --static at a directory your build already wrote:
npm run xano:deploy:ephemeral in a scaffolded project runs the second line for you. The deploy reports the frontend’s URL as static.url: Before archiving, the deploy writes the backend’s URL into every HTML document in the build as window.XANO_HOST, so the same build works on any backend with no rebuild. Read it at runtime with a build-time fallback:
--static-env KEY=VALUE (repeatable) adds more public config as window.<KEY>. Everything injected is served to the browser, so never put a secret there. Typed frontend covers calling your APIs from the app. A deploy with --static does not write .env.local: the frontend reads its backend URL at runtime.

Republish the frontend alone

xanosdk publish <dir> uploads a built directory and nothing else: no compile and no backend import. With no --to, it publishes to the backend this project last deployed to.
--to also takes ephemeral:<name>, local:<name>, workspace and tenant:<name>. Publishing to a workspace or a tenant asks before it replaces what its users see (--yes in CI). Publishing to the Engine includes a SvelteKit app’s server half (below).

How long a frontend URL lasts

A deploy that replaces the backend also clears its static hosting. A deploy without --keep-data takes the published frontend down, and with --static publishes it again, possibly at a new URL. The backend URL stays the same across the refresh. To keep the frontend serving through a backend change, merge instead:
When an ephemeral expires, its backend and frontend go with it.

Routing and size limits

The deploy infers whether the build is a single-page app or one document per route. --static-routing spa|multipage overrides that, and is rarely needed. Both are checked before anything is uploaded, so an oversize build stops the run with nothing written. An upload that fails after the backend landed leaves the backend in place, exits 3, and prints the xanosdk publish command that retries only the frontend.

Server rendering with SvelteKit on the Engine

On the Xano Engine, a SvelteKit app can render on the server. Build it with the SDK’s adapter, which needs esbuild in the app:
In a scaffolded SvelteKit project, SvelteKit’s config is the object passed to sveltekit() in vite.config.ts, and it already uses this adapter:
The scaffold prerenders every route from frontend/src/routes/+layout.ts. Stop prerendering the routes that should render per request. vite build then writes the client assets and prerendered pages, a 404.html fallback shell, and the server half in .xano-ssr/. Deploy it to the Engine:
The Engine serves files as files and renders every other path (a dynamic route, __data.json, a form action) through the server half. A server load reads the Engine’s URL as XANO_HOST:
Know three things about the server half:
  • It can hold secrets. SvelteKit inlines $env/static/private values into it, which is why the Engine never serves /.xano-ssr/.
  • It runs inside the Engine, not in Node. Keep state in your API, since module state is per runtime. Bodies are buffered (no streaming), request.formData() reads urlencoded forms only, and there is no AsyncLocalStorage. A render has 30 seconds and may answer up to 10 MB.
  • Other hosts serve only the static half. An ephemeral, a tenant or your workspace answers every non-file path with the 404.html shell, which boots the app in the browser. Prerendered routes and routes with a universal load work there; a route whose data comes from +page.server.js does not.

Next