Skip to content
Dashboard
Create 5 min read

Static Sites

Publish pre-built HTML, CSS, JavaScript, and assets without a long-running application server.

Static Sites#

A Static Site serves a generated directory of files. Choose it for plain HTML and for frameworks configured to produce a static export. Because no server process runs after the build, a Static Site does not use a start command or runtime health check — it simply uploads the files the build produced and serves them.

This simplicity is the feature: no ports, no health paths to keep alive, and no long-running process to supervise. When your app genuinely needs runtime execution (server rendering, API routes, middleware), a Frontend App is the right alternative.

When to use — and when not to#

Use Static Site when:

  • The deliverable is HTML/CSS/JS plus assets: plain HTML, a Vite/React build, an Astro static build, a Next.js app configured with output: "export", or a SvelteKit app with a static adapter.
  • Every page can be generated at build time and does not require a Node server at request time.
  • You want the smallest, most predictable deployment — build once, serve files.

Do not use Static Site when:

  • A route needs server rendering, an API route, middleware that inspects requests, or next/image optimization — choose Frontend App.
  • The backend is an API server that listens on PORT — choose Web Service.

Common output directories#

The publish directory is what the platform actually uploads after the build finishes. It must contain the final index.html and any referenced assets. A frequent error is publishing the source directory rather than the output directory.

ProjectTypical build commandPublish directoryWhat is published
Vite or Reactnpm run builddistBundled HTML, JS, CSS, and assets.
Astronpm run builddistStatic output generated by the Astro build.
Next.js static exportnpm run buildoutOutput produced only when output: "export" is set; contains static HTML per route.
SvelteKit with a static adapternpm run buildbuildFiles produced by the static adapter.
Plain HTMLnone.Hand-written index.html and assets already in the repository.

The directory must contain the final index.html and referenced assets. Review the detected framework and publish directory in the service configuration before deployment — stale assumptions from a different project can quietly point at the wrong folder.

Tip

Build locally before you deploy. Running the same npm run build on your machine and checking that dist (or out, or build) actually contains index.html catches mismatched publish-directory errors before you wait on a remote build.

Next.js static export#

Set output: "export" in the project’s Next configuration, build the project, and publish out. This produces a folder of static HTML — one file per route — with no Next.js server.

js
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = { output: "export" };
export default nextConfig;

Then build and publish:

bash
npm run build   # produces ./out when output: "export" is set
# publish directory in NexHost: out

Do not upload a normal .next directory to a Static Site; it needs a running server (next start) and should be deployed as a Frontend App. Uploading .next as static files produces an unroutable directory and misleading "index.html not found" errors.

For a mixed project that has both static pages and server-rendered ones, ship two services: the static marketing site as a Static Site and the server-rendered application as a Frontend App or Web Service, each with its own hostname.

Environment variables and build-time inlining#

Static sites bake configuration into the build artifact. A public analytics ID or API origin that your framework reads at build time (for example VITE_API_URL or NEXT_PUBLIC_API_URL) is inlined into the HTML/JS during npm run build. Changing it requires a new deployment so a fresh build can inline the new value.

Never put secrets in client-inlined variables — any NEXT_PUBLIC_ or VITE_ value ends up in the bundle that the browser downloads. Keep credentials in server-side runtime scopes on a service that actually runs a server.

Deploy#

  1. Select Static Site in New Project.
  2. Choose a repository, archive, or folder source. Confirm branch and root directory when offered.
  3. Set the build command (often npm run build or npm install && npm run build for a plain project) and the publish directory (dist, out, build, or .).
  4. Add any environment variables with the correct scope — typically Build for public static configuration.
  5. Deploy. Use the deployment detail page to check whether the configured output directory was found and contained index.html.

On success, the platform serves the published directory at the generated public hostname. You can then attach a custom hostname via Custom Domains.

Troubleshooting#

SymptomLikely causeFix
"Publish directory not found" or directory is emptyThe path points at source or a non-existent folderConfirm the output directory from your local npm run build and correct it in the service settings.
index.html missing, assets missingWrong directory or framework presetCompare the directory listing (ls dist / ls out) against the service configuration; update the publish directory.
Page shows but API/middleware routes return 404The app needs server rendering, not static filesRedeploy as a Frontend App from the source — do not ship .next as static.
Updated environment variable not reflectedStatic value baked at build time; no new artifact was producedStart a new deployment so a fresh build can inline the updated value.