Skip to content

Static sites

A static project is served from PandaStack’s global CDN with no pod. There is no server process, no scaling, and no cost — static sites are free on every plan. This is the right type for single-page apps (React, Vue, Svelte, Vite), static site generators (Gatsby, Astro without SSR), and plain HTML/CSS/JS.

The project’s build output is published to the CDN and served directly from there. In the routing manifest, a static project’s static.target points at the CDN origin (https://cdn.pandastack.io), and the manifest has zero function routes — there is no pod to dispatch to.

Because there is no server, static redirects are issued as 302 (by the static-plane Fastify proxy), whereas container redirects are 301. See Redirects, rewrites & headers for the full manifest walk.

There are two sources for a static project, and they behave differently:

SourceRuns a build?Redeployable from repo?
Static from GitYes — a server-side buildYes
Static uploadNoNo — you must re-upload

A static-from-Git project still runs a server-side build in a microVM. The build:

  • runs npm install (including postinstall)
  • runs the build command (default npm run build)
  • publishes the resulting output directory to the CDN

The build command and the output directory are what turn your source into publishable files. See Build & buildpacks for how the build works and where the build directory comes from per framework.

A static upload has a synthetic repository name of the form static-upload-*. It runs no build — you upload already-built files and PandaStack publishes them as-is. An upload cannot be redeployed from a repository; to change it you re-upload the files.

For a static-from-Git project, the build directory is the folder your framework writes its production output to. PandaStack’s auto-detect classifier knows the conventional output directory per framework:

FrameworkBuild output dir
Create React App (react-scripts)build
Vue CLI (@vue/cli-service)dist
Vite SPAdist
Gatsby (no SSR)public
Astro (no SSR)dist

If your framework writes somewhere else, set the output directory explicitly on the create form (or via outputDir in pandastack.json).

Static projects support a single-page-app fallback. When isSpa is true, any request that does not match a real file is served index.html instead of a 404. This is what lets a client-side router (React Router, Vue Router) handle deep links like /dashboard/settings — the browser loads index.html, and the router renders the right view.

In the routing manifest, the SPA fallback is tried after the static filesystem lookup and after any rewrites, and before the implicit 404. If SPA fallback is off, an unmatched path returns a 404.

Only variables your framework exposes at build time reach the client bundle. For example, Next.js inlines NEXT_PUBLIC_* variables; a Vite app inlines VITE_*. Runtime-only secrets are not baked into a static build — there is no server to read them at request time. This is a common source of confusion; see Environment variables & secrets for the full rule.

A static project gets https://{name}.pandastack.app by default and can attach a custom domain (paid). It supports redirects, rewrites, and headers — for static projects these are pure config applied by the static-plane proxy (no Kong sync).

Static sites run no pod, so they are free on every plan. Free organizations may run up to 5 static sites; paid plans allow unlimited. See Plans & limits. Note that bandwidth still counts against your monthly allowance.