Skip to main content

Deploy a React or Vite App for Free, With a Domain and Form

Published: •Last updated: Guides
reactvitedeploymentstatic website hostingcustom domainshtml forms

To deploy a React or Vite app for free, run npm run build and upload the folder it writes (dist/ for Vite) to a static host. On Statpio, drop that folder as a ZIP or run npx statpio deploy ./dist, and it goes live on a free onstatpio.com address with HTTPS, SPA Mode so routes don't 404 on refresh, a contact form that needs no backend and visitor statistics; your own domain needs Solo Pro. Netlify, Cloudflare Pages, GitHub Pages and Vercel's Hobby plan are free too, each with a catch, compared at the end.

Disclosure: this guide is published by Statpio, one of the tools compared. We link every competitor fact to its official source. Framework and host details were checked in their official docs on 9 November 2026.

Which React setups can I deploy as static files?

A React app that renders in the browser can, since it needs no server when someone visits. React's docs say the frameworks they recommend "can be deployed to a CDN or static hosting service without a server" (Creating a React App). Create React App has been deprecated for new apps since 14 February 2025, and React now points to a framework or "a build tool like Vite, Parcel, or RSBuild" (Sunsetting Create React App).

Your setupBuild commandFolder to upload
Vite with Reactnpm run builddist/
Create React App (maintenance mode)npm run buildbuild/
React Router framework mode, with ssr: falsereact-router buildbuild/client/
Next.js, with output: 'export'next buildout/

Source: Vite static deploy guide, Create React App deployment, React Router SPA guide, Next.js static exports, as of November 2026.

What doesn't move to a static host is code that has to run on a server when someone visits: server-side rendering, API routes, Next.js server actions, an Express server. Statpio hosts static output only. If your app needs those, use a host that runs server code, such as Vercel or Netlify.

How do I build a Vite app for production?

  1. Run npm run build. "By default, the build output will be placed at dist."
  2. Check the result with npm run preview, which serves dist at http://localhost:4173. Vite says the preview server "is intended for previewing the build locally and not meant as a production server".
  3. Leave base at its default, /: Statpio serves each website at the root of its own address. Of the hosts in this guide, only a GitHub Pages project site, served at <user>.github.io/<repo>/, needs base: '/<repo>/'; any host that serves the app from a sub-folder needs the same.

What about environment variables?

Variables prefixed VITE_ "will be exposed in client-side source code after Vite bundling", and Vite says they "should not contain sensitive information such as API keys" (Env Variables and Modes). A public value such as a publishable key or an analytics ID is fine; a secret needs a server, which a static host doesn't have. Note too that .env.local is meant to stay out of git (Vite says to add *.local to your .gitignore, which its project templates already do), so a build that runs on GitHub doesn't see it: commit public build values in .env instead.

How do I deploy the dist folder to Statpio?

Upload a ZIP (every plan)

  1. Create a free Statpio account, verify your email, click New website and name it. It gets an address such as my-app.onstatpio.com, with HTTPS.
  2. Open dist, select everything inside and compress it, so index.html is at the top of the ZIP.
  3. In Deployments, leave Deployment Type on Static Site and drop the ZIP on Drop your website ZIP here.

Uploads can be up to 25 MB on Free Forever and 50 MB on Solo Pro. Each upload is a new version, and Free Forever keeps the last 5 for one-click rollback. On Solo Pro and up, an upload can go to the website's staging address first, so you can try it before it goes live.

Deploy from the command line (every plan)

  1. In the website, open Integrations → API Keys, type a key name and click Generate Key. Copy the key: it's shown only once, and it works for that one website.
  2. Run npx statpio deploy ./dist --key <website API key> with Node.js 18 or newer. The command zips the folder, uploads it, waits until the new version is live and prints the address.

In CI, store the key as a secret named STATPIO_API_KEY and run npx statpio deploy ./dist after your build step, without --key. It works the same in GitHub Actions, GitLab CI or any runner with Node.js 18.

Push to deploy from GitHub (Solo Pro and up)

  1. Open Integrations → GitHub Actions, click Install GitHub App and give it access to your repository.
  2. Choose the repository under Select Repository and the Branch to deploy.
  3. Keep Install Command as npm install and Build Command as npm run build, and set Output Directory to your build folder (dist is the default).
  4. Click Connect Repository. Statpio commits .github/workflows/statpio-deploy.yml, and every push to that branch is built on GitHub Actions and published.

The workflow signs in to Statpio with short-lived GitHub tokens (OIDC), so there's no deploy secret to store in the repository. The publish your website guide has screenshots of these screens.

Why does my React app show a 404 when I refresh a page?

Because the route exists only in the browser. When someone opens /pricing directly, the host looks for a file at that address, finds none and answers 404. React Router's docs put it plainly: "you'll need to configure your host to direct all URLs to the index.html of the client build. Some hosts do this by default, but others don't" (React Router).

On Statpio, that's SPA Mode. It switches itself on when a deploy looks like a single-page app: exactly one HTML page, no 404.html, and build files such as Vite's assets folder. Check it, or turn it on yourself, under Settings → General → SPA Mode. With SPA Mode on, every address that isn't a file opens index.html, so let your router show its own "not found" page. For a site made of separate HTML pages, turn it off: a 404.html in the deploy is then served for missing pages.

Other hosts each have their own way: a /* /index.html 200 rule in a _redirects file on Netlify, a rewrite in vercel.json on Vercel, and automatic on Cloudflare Pages when the project has no top-level 404.html. Statpio doesn't read _redirects or vercel.json; SPA Mode does that job for client-side routes.

How do I add a contact form to a React app without a backend?

Use a plain form and let Statpio do the sending. It captures any form that uses method="POST" with no action, gives every field a name, and has no submit handler of its own: no onSubmit, no preventDefault(), no fetch(). Forms React renders after the page loads, on any route, are set up as soon as they appear.

export default function Contact() {
  return (
    <form method="POST">
      <label htmlFor="name">Name</label>
      <input id="name" name="name" type="text" required />

      <label htmlFor="email">Email</label>
      <input id="email" name="email" type="email" required />

      <label htmlFor="message">Message</label>
      <textarea id="message" name="message" required />

      <button type="submit">Send</button>
    </form>
  )
}

Statpio adds a visible Cloudflare Turnstile check and a hidden honeypot field itself, so don't add your own. It sends the form in the background, without a page reload, and shows a confirmation. A form with a password field, such as a sign-in form, is left alone. To keep Statpio away from any other form your own code sends, add a hidden input named __statpio_ignore.

Messages, file uploads included, arrive under Forms & Leads, and browser notifications tell you about new ones. Free Forever includes 250 submissions per website a month and Solo Pro 10,000; past the limit, up to the same number again is kept, locked until you upgrade. Test on the live address: capture happens on Statpio's servers, so npm run dev on your computer records nothing.

Visitor statistics need no code: Statpio adds a small cookieless analytics script to every page, and route changes in a single-page app count as pageviews. Every plan shows visitors, sources, pages, countries and devices; Solo Pro adds campaigns, goals, funnels and Core Web Vitals, which in a single-page app are measured on the first load.

How do I connect my own domain?

Custom domains come with Solo Pro ($9/month or $89/year, 5 domains included).

  1. Open Custom Domains, keep www. Domain, type your domain without the www (example.com) and click Connect Domain.
  2. At your registrar, create the two CNAME records it shows: www pointing to cname.onstatpio.com, and _acme-challenge.www pointing to the validation value from the dashboard, which ends in dcv.cloudflare.com.
  3. When the domain shows Active, SSL is set up. Forward example.com to www.example.com at your registrar, because Statpio serves root domains through www.

Where else can I deploy a React app for free?

HostWhat's freeYour own domain on the free planRefreshing a client-side routeThe catch
NetlifyFree plan: 300 credits a month; a production deploy uses 15Yes, with SSLAdd a /* /index.html 200 rule to _redirectsWhen the month's credits run out, every project pauses
VercelHobby planYes, up to 50 per projectAdd a rewrite to vercel.json"Non-commercial, personal use only"
Cloudflare PagesFree plan: 500 builds a monthYes, up to 100 per projectAutomatic when there's no top-level 404.htmlOne build at a time; 20,000 files per site; Cloudflare now says "Start new projects with Workers"
GitHub PagesFree for public repositories on GitHub FreeYesServes your 404.html for missing pagesNot for an online business or e-commerce site; a project site needs base set
StatpioFree Forever: 1 website on onstatpio.comNo: Solo Pro, $9/monthSPA Mode, on by itself for a typical buildA Statpio badge on Free Forever; forms and statistics included

Source: Netlify pricing and credits; Vercel Hobby plan and Vite on Vercel; Cloudflare Pages limits and serving; GitHub Pages overview, limits and 404 page; Statpio pricing. As of November 2026.

Which one fits depends on the project. All four free plans let you use your own domain. For a commercial site, rule out Vercel's Hobby plan (personal, non-commercial use only); for a shop or a site that runs your business online, rule out GitHub Pages too; Netlify's Free plan allows commercial projects, within its monthly credits. If the app needs server-side rendering or API routes, use a host that runs server code, such as Netlify, or Vercel on its Pro plan for commercial use. Statpio fits when the app needs a contact form and visitor statistics without adding other services, or when you run several small sites: Solo Pro covers 5 websites. Our Statpio vs Vercel comparison goes into the details.

Ready to deploy?

If npm run build gives you a dist folder, you can start free on Statpio, upload it, refresh a few inner routes and send a test message before you pay for anything. Hosting a site without a build step? See how to host an HTML website free, with forms and analytics.

Frequently asked questions

How do I deploy a React app for free?

Run npm run build and upload the folder it writes (dist for Vite, build for Create React App) to a static host. On Statpio's Free Forever plan it goes live on a free onstatpio.com address with HTTPS, form capture and visitor statistics. Netlify, Cloudflare Pages and GitHub Pages also have free plans, and Vercel's Hobby plan is free for personal, non-commercial use.

Why does my React Router app show a 404 when I refresh?

The route exists only in the browser, so the host finds no file at that address. The host has to serve index.html for those addresses. On Statpio that's SPA Mode, which switches itself on for a typical Vite build and can be checked under Settings, General. Netlify uses a _redirects rule, Vercel a rewrite in vercel.json, and Cloudflare Pages does it automatically when there's no top-level 404.html.

Can I deploy a Vite app with a custom domain?

Yes. On Statpio, custom domains come with Solo Pro at $9/month, with 5 domains included: add the domain on the Custom Domains page and create two CNAME records at your registrar, and SSL is set up automatically. The Free Forever plan uses a free onstatpio.com address instead.

How do I deploy a React app to GitHub Pages?

Vite's guide says to set base to your repository name with slashes for a project site, choose GitHub Actions as the Pages source in the repository settings, and add a workflow that runs npm run build and uploads dist. GitHub Pages is free for public repositories on GitHub Free, but GitHub says it isn't meant to run an online business or e-commerce site.

Can a React app have a contact form without a backend?

On Statpio, yes. Render a plain form with method POST, no action attribute, a name on every field and no onSubmit, preventDefault or fetch of your own. Statpio captures it on every plan, including forms React renders after the page loads, adds spam protection and puts the messages in your dashboard: 250 per website a month on Free Forever.

Should I still use Create React App?

Not for a new app. React deprecated Create React App for new apps on 14 February 2025 and recommends a framework, or a build tool such as Vite, Parcel or Rsbuild. An existing Create React App project still builds to a build folder, which deploys to a static host the same way.

Keep reading