Independent developer field guide
Edition 0012026
Guide · beginner

Ship a Vite React single-page app to production

Scaffold, build and deploy a Vite React single-page app to Netlify. Covers SPA redirects, custom domains and HTTPS, plus Cloudflare Pages and Vercel.

Before you start

  • Node.js version 22.23.4 or higher installed locally
  • npm package manager version 10.9 or later
  • Git installed and configured with a remote provider like GitHub
  • A Netlify account (free Starter plan is sufficient)

Vite is a common build tool and dev server for React single-page applications (SPAs). It uses native ES modules in development and bundles assets for production, which gives fast startup, hot module replacement (HMR), and optimized build output.

When deploying a client-side React single-page application to a static CDN such as Netlify, specific hosting rules are required to support browser-based routing (such as React Router). Without proper URL rewrite rules, visitors who refresh an internal route or follow a direct link will receive an HTTP 404 error from the CDN edge server.

This guide walks through scaffolding a React application with Vite, configuring the Netlify SPA rewrite rule, compiling production assets locally, pushing to Git, and setting up automated deployments with custom domains and HTTPS.


1. Prerequisites and local environment setup

Before you start, make sure your machine has a current Node.js runtime and npm.

Verify your installed versions:

node -v
npm -v

If your local Node.js version is below 22.23.4, update to a modern LTS release using your version manager:

nvm install 22.23.4
nvm use 22.23.4

You will also need an active account on Netlify or an equivalent static hosting provider, and a GitHub, GitLab, or Bitbucket account.


2. Scaffolding the React application with Vite

Vite provides the create-vite CLI to scaffold new projects from templates. We will create a standard React app by passing the project name and template flag.

Run this command in your workspace directory:

npm create vite@latest vite-react-site -- --template react

Navigate into the created folder and install dependencies:

cd vite-react-site
npm install

The scaffolding process creates a minimal React project containing:

  • index.html: The HTML shell where Vite injects the root module script.
  • src/main.jsx: The application entry point mounting React 19 into the DOM root.
  • src/App.jsx: The starter React component.
  • vite.config.js: The Vite configuration file loading @vitejs/plugin-react.
  • public/: The directory for static assets that Vite copies unchanged into the output directory.

For all templates and flags, see the Vite Getting Started Guide.


3. Configuring single-page application (SPA) redirects

In client-side single-page applications, page navigation is handled dynamically inside the browser via the HTML5 History API. When a user clicks a navigational link within the application, JavaScript updates the URL without triggering a full page reload.

However, when a visitor opens a deep URL directly (such as /dashboard or /profile) or refreshes the page, the browser sends an HTTP GET request to the CDN edge server. Because the static server only has physical files for /index.html and assets in /assets/, it cannot find a file at /dashboard and returns an HTTP 404 Not Found error.

To solve this, Netlify supports redirect and rewrite rules defined in a plain text file named _redirects placed inside the publish directory.

Create public/_redirects with the following rewrite rule:

/*  /index.html  200

You can create this file directly from your terminal:

echo '/*  /index.html  200' > public/_redirects

Why this rule is necessary

As explained in Netlify Rewrites and Proxies Documentation:

  • Assigning an HTTP status code of 200 converts a redirect rule into a rewrite.
  • A rewrite serves the content of /index.html behind the scenes while keeping the original URL in the visitor address bar.
  • The /* catch-all pattern routes every incoming request path to index.html, allowing the client-side React router to inspect the window location and render the matching view component.
  • Because Vite automatically copies any files located in the public/ directory directly into the root of dist/ during the build process, placing _redirects in public/ ensures it lands in the final deployment directory without any extra build scripts.

4. Testing the production build locally

Confirm that the app builds cleanly and produces the expected assets before you deploy.

Run the production build command:

npm run build

As documented in the Vite Static Deploy Guide, vite build writes the production output to dist by default, and vite preview serves that folder locally. Files in public/ are copied to the root of dist/ unchanged, as the Vite Static Assets Guide explains.

Confirm that dist/index.html and the copied dist/_redirects file exist:

ls -la dist/index.html
ls -la dist/_redirects

To preview the production bundle locally, served the way a real web server serves it, run:

npm run preview

Vite starts a local HTTP server serving assets directly from dist/ at localhost:4173. Open your browser and navigate to the printed address to verify that styles, assets, and component state initialize without errors. Press Ctrl+C to terminate the preview server.


5. Connecting a Git repository

Continuous deployment platforms monitor remote Git branches and trigger automatic production builds whenever code is pushed.

Initialize Git in your project root and make your first commit:

git init
git add .
git commit -m 'Initial commit of Vite React SPA with Netlify redirects'

Create a new repository on GitHub (or your preferred Git provider) and push your local branch:

git remote add origin [email protected]:your-username/vite-react-site.git
git branch -M main
git push -u origin main

We did not run this step for this guide.


6. Configuring Netlify build and deploy settings

Connecting your repository to Netlify gives you automatic preview builds for pull requests and production deploys for merges into main.

Dashboard setup

  1. In the Netlify web app, select Add new site > Import an existing project.
  2. Select your Git provider and choose the vite-react-site repository.
  3. Configure the build parameters in accordance with the Netlify Configure Builds Overview:
    • Base directory: Leave blank (root of repository).
    • Build command: npm run build.
    • Publish directory: dist.
  4. Click Deploy site.

Netlify executes dependency installation, runs npm run build, and copies the contents of dist/ to its global CDN.

Setting up netlify.toml

You can also put these build settings in a netlify.toml file in the project root:

[build]
  command = "npm run build"
  publish = "dist"

[build.environment]
  NODE_VERSION = "22.23.4"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

You can declare the same SPA rule in netlify.toml, as shown above. This guide keeps it in public/_redirects so the rule ships with the build output.

We did not run this step for this guide.


7. Configuring a custom domain and automatic HTTPS

Every site deployed to Netlify receives a default address ending in .netlify.app. For production applications, you should connect your branded custom domain.

Setting up DNS records

Follow the instructions in the Netlify Custom Domains Guide:

  1. In the Netlify project overview, select Domain management in the left sidebar.
  2. Click Add a domain and enter your domain name (e.g., app.example.com or example.com).
  3. Add the corresponding DNS record at your domain registrar:
    • For subdomains (such as app.example.com): Create a CNAME record pointing to your Netlify site address (your-project.netlify.app).
    • For root domains (example.com): Use Netlify DNS, or an ALIAS or CNAME-flattening record if your DNS provider supports it.

Automatic HTTPS certificates

As documented in Netlify Secure Domains with HTTPS:

  • Netlify provisions a free Let's Encrypt SSL/TLS certificate when you add a custom domain.
  • Certificate creation is automatic after you add the domain.
  • Renewal of Netlify-provisioned certificates is automatic. Custom certificates that you upload must be renewed manually.

We did not run this step for this guide.


8. Alternative deployments: Cloudflare Pages and Vercel

Vite's static output in dist/ is not tied to one cloud and deploys to other static hosts with little configuration.

Cloudflare Pages

Cloudflare Pages can host the static dist/ output. Deploying a Vite React app follows the steps in the Cloudflare Pages React Deployment Guide:

  1. In the Cloudflare dashboard, go to Workers & Pages and create a Pages project connected to your Git repository.
  2. Select your Git repository.
  3. In build configuration:
    • Build command: npm run build.
    • Build output directory: dist.
  4. Deploy the project.

For custom domains, open the Custom domains section of your Pages project and enter your domain, following the Cloudflare Pages Custom Domains Guide. If your domain has CAA records, they must allow Cloudflare to issue a certificate for it. Cloudflare Pages also reads a _redirects file placed in the static asset directory, as described in the Cloudflare Pages Redirects documentation, so the public/_redirects rule carries over.

We did not run this step for this guide.

Vercel

Vercel's Vite guide describes how to deploy a Vite project:

  1. Import your GitHub repository in the Vercel dashboard.
  2. Vercel detects Vite and applies its framework defaults.
  3. To configure SPA rewrites on Vercel, add a vercel.json file in your repository root with a rewrite from "source": "/(.*)" to "destination": "/index.html".
  4. To attach a custom domain, open Settings > Domains for your project and follow the DNS guidance documented in Vercel Custom Domains Documentation.

We did not run this step for this guide.


9. Common troubleshooting and fixes

These are fixes for common configuration errors when shipping Vite React apps.

Problem 1: 404 error on page refresh or direct link

  • Symptom: Navigating inside the app works properly, but refreshing /about or opening a direct link returns Page Not Found (HTTP 404).
  • Cause: Client-side routing requires the host server to route all unknown path requests back to the single-page application entry point (index.html).
  • Fix: As documented in Netlify Rewrites and Proxies, ensure public/_redirects contains /* /index.html 200 and confirm that dist/_redirects is present after running npm run build.

Problem 2: Environment variables return undefined in browser

  • Symptom: Logging import.meta.env.API_URL or process.env.API_URL outputs undefined in browser developer tools.
  • Cause: To prevent confidential server credentials and tokens from leaking into public client bundles, Vite filters out all variables that do not carry the designated client prefix.
  • Fix: As the Vite Environment Variables Guide explains, rename the variable in your .env file to start with VITE_ (for example, VITE_API_URL=/api/v1) and reference it in React code via import.meta.env.VITE_API_URL.

Problem 3: Blank white screen after deployment

  • Symptom: The site loads without a 404 error, but the browser displays a blank white screen and the browser console logs 404 errors for script and style files in /assets/.
  • Cause: The application is deployed under a subpath, but Vite's default base is /, so loaded chunk URLs point to the site root.
  • Fix: In vite.config.js, set the base property to the path the app is served from, or to ./ for relative asset URLs, as described in the Vite Build Guide. Also verify in Netlify Configure Builds Overview that your publish directory is set to dist.

Problem 4: Remote build fails with Node version errors

  • Symptom: Remote CI builds fail during npm install or vite build with engine incompatibility warnings or syntax errors.
  • Cause: The build server is utilizing an older default Node.js version.
  • Fix: Refer to Netlify Dependency Management and specify the expected Node.js version by setting the NODE_VERSION environment variable in the dashboard or placing a .node-version file containing 22.23.4 in the repository root.

Expected result: A production bundle in the dist directory containing compiled JavaScript chunks, hashed CSS, optimized static assets, and the SPA redirect rule ready for immediate edge deployment.

If something goes wrong

Problem Fix
Direct navigation or page refresh on non-root URL paths returns HTTP 404 Not Found Add public/_redirects containing /* /index.html 200 so the edge server rewrites all requests to index.htmldocs.netlify.com
Environment variables return undefined in client-side React components Prefix public client variables with VITE_ and access them through import.meta.env.VITE_NAMEvite.dev
Site deploys successfully on hosting dashboard but renders a blank white screen Set base in vite.config.js to the path the app is served from, or to a relative base such as ./ if that path is not known in advancevite.dev
Build step fails on cloud platform due to outdated Node.js runtime version Declare the target version using a .node-version file in repository root or set NODE_VERSION environment variabledocs.netlify.com