Back to Blog
Tutorial9 min read2026-07-03

How to Deploy a SolidJS / SolidStart App

SolidJS ships as a static SPA; SolidStart is full-stack SSR. Here's how to deploy both — the SPA as a free static site, the SSR app as a container — with build config and routing.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

Two Solid apps, two deploy shapes

Solid comes in two flavors that deploy very differently:

  • SolidJS (with Vite) builds to a static SPA — HTML, CSS, JS files. Deploy it as a static site; it's free and globally fast.
  • SolidStart is the full-stack meta-framework with SSR, server functions, and API routes. It needs a running server, so deploy it as a container.

Knowing which you have determines everything. Let's cover both.

Path A: SolidJS SPA as a static site

A Vite-based Solid app builds to a dist/ folder:

// package.json
{
  "scripts": {
    "build": "vite build",
    "preview": "vite preview"
  }
}
npm run build   # outputs to dist/

Deploy as a PandaStack static site. The platform auto-detects the Vite framework, runs vite build, and serves dist/. Static builds run in pandastack.ai microVMs, and the output is served globally. Static sites are unlimited on Pro and Premium, and the free tier includes 5 static sites — so a Solid SPA can be hosted at $0/mo.

SPA routing fallback

Client-side routing (solid-router) needs all unknown paths to serve index.html, or deep links 404. For a static SPA this is the standard SPA fallback — configure your routes to rewrite to index.html. Most static hosting (PandaStack included) supports an SPA fallback for exactly this.

Path B: SolidStart SSR as a container

SolidStart uses Vinxi/Nitro under the hood and can target a Node server. Set the Node preset:

// app.config.js
import { defineConfig } from '@solidjs/start/config';

export default defineConfig({
  server: { preset: 'node-server' },
});

Build produces a server bundle you run with Node:

{
  "scripts": {
    "build": "vinxi build",
    "start": "node .output/server/index.mjs"
  }
}

The Nitro Node output reads the PORT env var automatically, so it binds to the platform's injected port without changes.

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

FROM node:20.18-slim
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/.output ./.output
EXPOSE 3000
CMD ["node", ".output/server/index.mjs"]

Or skip the Dockerfile — PandaStack auto-detects Node and the build/start commands.

Step: Add data with a managed database

SolidStart server functions can talk to a database. Attach a managed PostgreSQL and read the injected DATABASE_URL inside a server-only module:

// db.server.ts
import postgres from 'postgres';
export const sql = postgres(process.env.DATABASE_URL!);

Use it inside a "use server" function or a route's server handler so it never ships to the client.

Step: Deploy

Connect your repo and push:

git push origin main

For the SPA path, the static build runs and deploys to the global edge. For the SSR path, the build runs in a rootless BuildKit K8s Job pod, ships to Artifact Registry, and Helm-deploys. Either way you get live build logs, a custom domain, and automatic SSL.

Which should you choose?

SolidJS SPASolidStart SSR
OutputStatic filesNode server
Deploy asStatic site (free)Container
SEOClient-renderedServer-rendered
Data fetchingClient / external APIServer functions
Cost$0 on free staticWeb service tier

If you don't need SSR or server functions, the SPA path is simpler and free. Reach for SolidStart when you need server-side rendering, server functions, or co-located data access.

References

  • [SolidStart — deployment](https://docs.solidjs.com/solid-start/getting-started)
  • [SolidStart configuration & presets](https://docs.solidjs.com/solid-start/reference/config/define-config)
  • [Vite — static deploy](https://vite.dev/guide/static-deploy)
  • [Nitro deployment presets](https://nitro.build/deploy)

---

Solid scales from a free static SPA to a full SSR app without changing frameworks. Host the SPA free or run SolidStart as a container with an auto-wired Postgres — start on PandaStack's [free tier](https://dashboard.pandastack.io) and pick the path that fits.

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also