What The React Hosting Options Are For A Static Build

You cannot host a React project, only what its build produces. Here are the React hosting options for a dist folder, plus the two things that always break.
The OxyPages Team · · 9 min read
Your React app runs fine on localhost and now you need it at a real address. So you go looking for a host, and every answer starts talking about git providers, build commands and framework presets.
Park all of that, because the React hosting options only make sense after one fact nobody says out loud: you cannot host your project. A React project is source code, and no web server knows what to do with a .jsx file.
What you host is the folder npm run build produces. It is plain HTML, CSS and JavaScript, a static website like any other, and it goes anywhere a static website goes.
Then the question mostly answers itself, and what is left is the two ways a good build breaks the moment it leaves your laptop.
TL;DR: You do not host a React project, you host its build output. Run npm run build and upload the folder it creates: dist for Vite, build for Create React App, out for a Next.js static export. Two things break: the page goes blank when the app sits in a subfolder and the base path was not set, and deep links 404 on refresh unless the host rewrites unmatched paths to index.html. If your Next.js app uses API routes, server rendering or server actions, no static host can run it.
Why You Cannot Just Upload Your Project Folder
Your project folder is a set of instructions for a build tool. It is not a website.
Open src/App.jsx and the first line is an import. The file is written in JSX, which is not HTML and no browser has ever parsed it. None of it was meant to be shipped: it is meant to be read by a build tool and turned into something a browser understands.
The build does four jobs:
- Converts JSX and TypeScript into plain JavaScript
- Follows every
importand bundles the pieces into a few files - Hashes the filenames, so
index-C8xk2p.jscaches forever and still updates when you change something - Rewrites
index.htmlto point at the new names
Out comes one folder, and that folder is the website. Everything else stays on your disk.
I have watched more than one person zip their entire project, node_modules included, and drag 300 MB onto an upload page. It fails, and it should. What a static host actually serves is the short version.
What Your Build Command Actually Produces
One command, and the output folder depends on the tool.
| Tool | Command | Output folder | Rename it with |
|---|---|---|---|
| Vite | npm run build | dist | build.outDir in vite.config.js |
| Create React App | npm run build | build | not configurable |
| Next.js static export | npm run build | out | distDir in next.config.js |
Open the folder and there is less in it than you expect:
index.html, a nearly empty page whose body is one<div id="root">plus tags loading your JavaScript and CSS- an
assetsfolder holding the bundled files, with hashes in the names - anything from
public, copied across untouched
That is the whole website, usually a few hundred kilobytes. React itself is compiled into those bundles.
A word on Create React App, since plenty of projects still use it. It was deprecated in February 2025 and is now in maintenance mode, and the React docs steer new projects to a framework or a build tool like Vite. the React team on sunsetting Create React App Deployment does not change: your build folder still hosts the same way.
The Two Things That Break After You Upload

Both give you a page that worked on your machine and does nothing at a real address. Neither is a bug in your code.
A Blank White Page With 404s In The Console
This is a wrong base path, the most common React deploy failure there is.
Vite's base option defaults to /, so the built index.html asks for /assets/index-abc123.js, an absolute path from the root of the domain. the Vite base option
At the root of a domain that is correct and it works first time.
In a subfolder like example.com/my-app/, the browser obediently asks for example.com/assets/index-abc123.js, nothing is there, and you get a white page with a console full of 404s. GitHub Pages project sites hit this constantly.
Two fixes:
- Set the base to the subpath and rebuild:
base: '/my-app/'invite.config.js, or runvite build --base=/my-app/. - Or set
base: './'so every asset path is relative and the build works wherever it lands.
Create React App has the same setting under another name: the homepage field in package.json, set to the subpath or a single dot.
A 404 When You Refresh On A Deep Link
Click through your app to /about and it works. Refresh, and you get a 404. Send that link to somebody and they get a 404 too.
This one is worth understanding rather than copying a fix, because it is a real limit of static hosting.
Your router runs in the browser. When you click a link no request leaves the machine: React Router rewrites the address bar with the History API and swaps the component out. The server never hears about it.
Refresh, and the browser makes a real request for /about. The host looks for a file there. Your build has exactly one HTML file, so there is nothing to serve and it returns a 404, correctly.
The fix is a catch-all rewrite: any path the host cannot find serves index.html anyway, with a 200 status, and the router works it out from the URL. On Netlify that is a _redirects file containing the line /* /index.html 200. Cloudflare Pages does it by default when your build has no top-level 404.html. Vercel does it automatically for frameworks it recognises.
Not every host offers it. OxyPages does not, so a router-driven app 404s on refresh. What works there is publishing a copy of index.html named 404.html: it is served at the address the visitor asked for, path intact, so the router boots and takes over. The cost is a 404 status code, fine for an internal tool and wrong for anything you want indexed.
The other escape hatch is a hash router. With example.com/#/about the request never leaves the root path, so the server always serves index.html. It works anywhere with no configuration, at the price of uglier URLs that search engines read as one page.
Where The React Hosting Options Actually Differ
For a plain Vite build, barely at all. They all serve static files and your bundle will not notice.
| Host | How you deploy | Catch-all rewrite for a SPA | Next.js server features |
|---|---|---|---|
| Netlify | Git, CLI, or drag the folder | Yes, via a _redirects file | Yes, first-class |
| Vercel | Git, CLI, or drag the folder | Yes, automatic for known frameworks | Yes, first-class |
| Cloudflare Pages | Git or folder upload | Yes, default with no 404.html | Partial, through an adapter |
| GitHub Pages | Commit the build to a repository | No rewrite rules at all | No |
| OxyPages | Drag the folder or a zip | No, only the 404.html copy trick | No |
Two honest notes on that table.
Vercel and Netlify have first-class Next.js support a plain static host cannot have. If your app renders on the server, exposes API routes or regenerates pages on a schedule, they run it as an application. A static host only serves files, so the most it can do is serve a Next.js static export. That is a different product, not a worse one, and picking the wrong one wastes an afternoon.
GitHub Pages is the one to watch for a single-page app. It has no rewrite rules, so deep links 404 and stay that way. The usual workaround is a 404.html that re-encodes the path in JavaScript and bounces the visitor to index.html. It works, and it flickers.
Every host in that table has a free tier that will carry a React build, so where free tiers draw the line matters more than price.
When A Static Host Is The Wrong Answer
Sometimes the build output is not the whole app, and then none of this helps.
Next.js is the clear case. It only produces a static folder if you ask it to, using the export output mode in next.config.js:
// next.config.js
const nextConfig = {
output: 'export',
}
module.exports = nextConfig
Set that and the build writes an out folder you can upload anywhere. But switching it on switches off everything that needs a running server: server actions, incremental static regeneration, route handlers that read the request, cookies, rewrites, redirects and headers set in next.config.js, draft mode, intercepting routes, dynamic routes without generateStaticParams, and image optimisation with the default loader.
If your app uses any of those the export will not build, and no static host can rescue it. You need a platform that runs Node, and that is the honest answer even if it is not the one a hosting article wants to give.
The same logic scales outward. You need a server, not a static host, when:
- Server-side code has to talk to a database
- An API key has to stay out of the browser
- Sign-in is checked on the server, not trusted from the client
- The HTML differs per visitor at request time
Calling a third-party API from the browser is different, and it is fine. Supabase, Firebase, a Stripe checkout link, any public REST endpoint: those requests come from the visitor's browser, not from your host.
What To Do Next
About five minutes, in this order:
- Run
npm run buildand open the folder it created. If nothing appears, check thebuildscript inpackage.json. - Decide where the app will live. Root of a domain, or a subfolder? If a subfolder, set the base path and build again.
- Check whether the app has client-side routes. If it does, you need a host that rewrites unmatched paths to
index.html, a hash router, or the404.htmlcopy above. - Upload the build folder, not the project folder. If the host wants a zip, zip the contents rather than the folder, or the site lands one directory too deep.
- Open the live URL, click every route, then hard-refresh on each one. That test catches both failures above.
Drop your build folder onto OxyPages if you want it live in a drag with no repository to connect, or pick whichever host in the table matches your routing.
And if what you actually have is one exported page with a stylesheet beside it, hosting a plain HTML file is a much shorter road.
FAQ
Can I Host A React App On Any Static Host?
Yes, provided you upload the build output rather than the project. Any host that serves HTML, CSS and JavaScript will serve a Vite or Create React App build without caring what made it. Check one thing first: whether it rewrites unmatched paths to index.html, which a single-page app needs so deep links survive a refresh.
Do I Need Node.js Running On The Server?
No. Node runs on your machine during the build, not on the host. Once npm run build has finished the output is ordinary files, and the server's only job is to hand them over. That is why so many hosts work.
Why Is My Deployed React App Just A Blank Page?
Almost always the base path. Open the browser console: if you see 404s for files under /assets/, the build is asking for its assets at the root of the domain while the site is served from a subfolder. Set base in vite.config.js, or homepage for Create React App, then rebuild.
Can I Host A Next.js App On A Static Host?
Only if it builds as a static export, which means adding the export output mode to next.config.js so Next.js writes an out folder. That switches off server actions, API routes that read the request, incremental static regeneration, default image optimisation and more. If your app needs any of them it needs a server that runs Node, and no amount of choosing between the React hosting options will change that.