Deploy React with Vite on Lizard
Lizard builds a React app that uses Vite and serves its dist/ directory through nginx on port 80. This guide covers a browser-rendered app. For React pages that need a server, follow the Next.js guide or provide a production server for your chosen React framework.
Prepare the build
Use an existing React and Vite project with a committed lockfile. Its package.json needs a production build script:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}If your scaffold runs TypeScript checks before vite build, keep those checks. Keep Vite’s default dist output directory. A custom build.outDir needs a matching Dockerfile because the standard detection path copies dist.
| Setting | Value |
|---|---|
| Detection | vite in dependencies or dev dependencies |
| Build | npm run build |
| Output | dist/ |
| Production server | nginx; no Node start script needed |
| Service port | 80 |
Test locally
npm ci
npm run build
npm run previewOpen the local preview URL and test a page that calls your API. The preview command checks the build locally; do not set vite preview as the production start command. See Vite deployment.
Deploy the source
After CLI setup, run from the directory containing package.json:
lizard init --name react-app
lizard add --service web
lizard up --service web --port 80
lizard logs --build --service web --json
lizard ps --jsonUpload source and the lockfile, excluding node_modules/, dist/, and secrets. Leave service build/start overrides unset to use the static detection path. The nginx container listens on port 80 even though the development and preview servers use other ports.
Connect an API
Use a public variable such as VITE_API_URL for the API’s browser-reachable HTTPS address. Read it as import.meta.env.VITE_API_URL. Configure that value through variables and secrets and rebuild when it changes. Never expose a database URL, API credential, or internal-only service address through a VITE_* variable.
For an API on another origin, configure its allowed origins to include the frontend URL. A private service hostname that works between backend services will not resolve in a visitor’s browser.
Verify routing
Open the live app, follow a client route, then reload that URL directly. The default static server falls back to index.html so the client router can render an inner route. Add a route for unknown paths in the React app too. That fallback still returns HTTP 200; use static routes and 404s to choose a server policy for pages that need real HTTP 404 responses.
If an asset returns HTML or the page goes blank, check Vite’s base, the requested asset URL, and the output directory. If the app never becomes healthy, check that the service port is 80 and that an old start-command override has not selected a different build path.
For pages meant to appear in search, inspect the initial HTML response. A browser-rendered shell may not contain the text you expect a search engine or answer engine to read. Choose prerendering or a server framework when you need that text in the response.
See tested versions and cloud results for the September 9, 2026 deployment checks and their limits.
Updated