Deploy a React Vite app from GitHub: step by step
Deploy a React app built with Vite from GitHub. Voroa runs npm run build, serves the dist folder with working client-side routes, and puts it on free HTTPS.
To deploy a React app built with Vite on Voroa, push it to GitHub, create a Web Service from the
repository, leave the build and start commands empty, and select Deploy. Voroa installs your
dependencies, runs npm run build, and serves the dist folder on a live HTTPS URL, with
client-side routes that keep working when a visitor refreshes the page.
The short version:
- Check that
package.jsonhas"build": "vite build"and that Vite writes todist(the default). - Push the project to GitHub.
- In Voroa, select New service, choose Web Service, and pick the repository and branch.
- Leave Build command and Start command empty.
- Add any
VITE_environment variables and tick Build-time for each. - Select Deploy and open your URL.

What you need before you start
- A React project created with Vite, in a GitHub repository.
- A
buildscript inpackage.json. Projects created withnpm create vite@latestalready have"build": "vite build". - The build output in the
distfolder, which is Vite’s default.
You do not need a Dockerfile, a server or nginx. You also do not need to add a static file server
such as serve to your dependencies.
Step 1: Check your Vite build output
Run the build once on your machine:
npm run build
Vite writes the finished site to dist/, with an index.html at the top of that folder. That
dist/index.html is what Voroa serves.
If you changed build.outDir in vite.config.js, keep it as dist, or at least as a plain string
Voroa can read. A path that is computed in code (for example with path.resolve) is not detected:
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
build: { outDir: 'dist' },
})
If the folder is wrong, the deploy stops with a clear message instead of publishing an empty site: “Your build finished, but there is no site to serve: index.html was not found.”
Step 2: Create a web service
In the Voroa dashboard, select New service, choose Web Service, and pick your repository and
branch. If the React app lives in a subfolder, such as /frontend in a monorepo, set
Root directory to that folder.

Step 3: Leave the build and start commands empty
For a Vite app, Voroa detects the project and does the work itself:
| Stage | What Voroa runs |
|---|---|
| Install | Your package manager’s install, chosen from your lock file |
| Build | Your build script, run with your package manager |
| Serve | The files in dist, on the port Voroa provides |
If you do set a Build command, make it one that builds. A Build command replaces the automatic build step.
npm installon its own builds nothing, and installing again only makes the build slower, because Voroa has already installed your dependencies. Usenpm run build, or leave the field empty.
Client-side routes keep working
React Router and other client-side routers handle paths such as /dashboard in the browser. When a
visitor refreshes on that path, the server has to answer with index.html instead of a 404. Voroa
does this for you, so deep links and refreshes work without any rewrite rules.
Step 4: Add environment variables
Vite reads environment variables while it builds, not when the page loads, and it only exposes
variables whose names start with VITE_:
const apiUrl = import.meta.env.VITE_API_URL
Open the service, go to Environment, add each variable, and tick Build-time so the build can see it.

Two rules matter here:
- Anything starting with
VITE_ends up in the JavaScript your visitors download. Put only public values there, such as an API URL. Never put a secret key in aVITE_variable. - A change needs a new build. Because the value is baked into the bundle, redeploy after you
change a
VITE_variable.
Step 5: Deploy
Select Deploy. The build log shows each stage live: cloning your branch, installing dependencies,
running vite build, and starting the site. When it finishes, your app is live at
https://your-app.onvoroa.com.
Turn on auto-deploy and every push to your branch ships a new build. Choose the Node.js version under Environment if your project needs a specific one.
Web service or static site?
Voroa can host a React app in two ways:
| Web service (this guide) | Static site | |
|---|---|---|
Who runs npm run build |
Voroa, on every deploy | You, before you commit |
| What you commit | Source code only | The built dist folder |
VITE_ variables |
Set in Voroa, applied at build | Baked in when you build locally |
| Best for | Most React apps | Sites you already build in CI |
If you are unsure, use a web service. You never have to commit build output, and every push rebuilds.
Common React (Vite) deploy errors and fixes
| Error | Cause | Fix |
|---|---|---|
| “index.html was not found” | The Build command only installs, or Vite writes somewhere other than dist |
Leave the Build command empty or set it to npm run build, and keep outDir as dist |
import.meta.env.VITE_... is undefined |
The variable is missing, lacks the VITE_ prefix, or is not marked Build-time |
Rename it with VITE_, tick Build-time, then redeploy |
A blank page with 404s for /assets/... |
base in vite.config.js points at a sub-path |
Remove base or set it to '/' |
| The build runs out of memory | A large app needs more memory to bundle than the build machine has | Builds run on the build machine your plan includes, not on your service’s instance type; a paid plan gets a larger one. See build pipeline |
| The live site still calls your development API | The API URL is hard-coded in the source | Read it from import.meta.env.VITE_API_URL |
Frequently asked questions
Do I need serve or nginx to host a React app?
No. Voroa builds your Vite app and serves the dist folder itself, including the fallback to
index.html that client-side routing needs. Leave the Start command empty.
Does this work for Vue, Svelte or other Vite apps?
Voroa builds and serves single-page apps made with Vite the same way, including Vue, Svelte, Preact and Solid. SvelteKit, Remix and React Router in framework mode are different: they run their own server, so deploy them like a Node.js app.
Can I use pnpm or Yarn?
Yes. Commit your lock file (pnpm-lock.yaml or yarn.lock), and Voroa installs with the matching
package manager.
How do I connect my React app to a backend?
Deploy the backend as its own web service, for example a Node.js API, and
pass its URL to the React app as VITE_API_URL. Allow your frontend’s domain in the backend’s CORS
settings.
Can I use my own domain?
Yes. Add a custom domain to the service, and Voroa issues and renews its HTTPS certificate.
Next steps
- Add a custom domain with automatic HTTPS
- Deploy a Node.js backend to pair with your React frontend
- Enable auto-deploy on every push
- Environment variables