The best React hosting platforms in 2026
If your React app is a Vite or Create React App build — client-side rendered, no server framework — then hosting it is, technically, solved. `npm run build` produces a folder of hashed static files. Any host that can serve files over HTTPS with a CDN in front will serve them correctly and quickly.
Which is why nobody's actual React hosting problem is the files. It is one of three things the folder cannot do on its own: rewrite unknown URLs back to index.html so client-side routing works, hold a secret so it can talk to an API, and be an API. Every platform below is a different answer to those, and the pricing differences are mostly a proxy for how it answers the third one.
Disclosure: PandaStack is mine. It appears where it is genuinely useful and not at the top of a list where it isn't.
The three things that are not the files
- SPA fallback routing. Your router owns /dashboard/settings, but the server has no such file. Without a rewrite rule sending unknown paths to index.html, a hard refresh on any route returns 404 — the single most common React deployment bug.
- Build-time environment variables. Anything in VITE_ or REACT_APP_ is baked into the bundle at build time and is public. There is no such thing as a secret in a client-side React app, and every year someone ships an API key by treating one as private.
- The API. If your app talks to a backend, you now need CORS configured, or a proxy, or the API on the same origin. This is where a static host stops being sufficient and the hosting decision becomes real.
# The SPA fallback in three flavours — one of these is your 404 bug
# nginx
location / { try_files $uri $uri/ /index.html; }
# Caddy
try_files {path} /index.html
# Any platform's own config (Netlify _redirects, Vercel rewrites, etc.)
/* /index.html 200Static hosts — the right default
Cloudflare Pages and Netlify
Both do the boring things well: connect a repo, build on push, serve from a global CDN, handle the SPA rewrite with one config line, issue certificates, and give you deploy previews per pull request. Free tiers are genuinely usable for real projects. Cloudflare's bandwidth position is hard to beat if your app is popular; Netlify's ergonomics around redirects and forms remain excellent.
Vercel
Fine for an SPA, though you are buying a platform built around Next.js and using a fraction of it. Worth it if the rest of your organisation is already there or you expect to move to Next.js later. Otherwise you are paying Next.js prices for a folder of files.
S3 plus CloudFront, or any object storage with a CDN
Cheapest at scale and the most work to set up: bucket policy, distribution, cache invalidation on deploy, and a custom error response mapping 404 to index.html. If you already have AWS infrastructure and a CI pipeline, this is a couple of hours and then it never changes.
GitHub Pages
Free and perfectly good for docs, demos, and portfolios. The SPA fallback requires the well-known 404.html workaround, and there is no server-side anything, so treat it as a publishing target rather than a hosting platform.
When the API changes the answer
The moment your React app needs a backend you control — session cookies, a database, a webhook receiver, server-side API keys — you have two workable shapes. Either keep the frontend on a static host and run the API separately, accepting CORS and a second deploy target, or serve both from one place so the browser sees a single origin.
The single-origin option is underrated. Same-origin means no CORS preflight, cookies work without SameSite gymnastics, and you can proxy /api to your backend without the browser knowing there are two processes. Render, Railway, Fly, and PandaStack can all do this.
PandaStack — static when it's static, a VM when it isn't
PandaStack detects Vite, CRA, and raw webpack SPA builds, runs the build inside a microVM, and then — if the output is genuinely static — serves the built files directly with no VM left running. You get the static-host economics without maintaining a separate pipeline, and the build gets a real machine with 4 GiB of RAM, which matters more than it should for anyone who has watched a large React build die with a JavaScript heap out-of-memory error on a constrained builder.
When the same repo grows an Express or FastAPI backend, the app becomes a running microVM serving both, on one origin, without changing platforms. That continuity is the reason to choose it over a pure static host; if your app is a permanent SPA with no backend ambitions, Cloudflare Pages is a simpler answer and I'd say so.
# Vite is detected; the built output is served statically, no VM kept running
pandastack app create --name web \
--git-url https://github.com/acme/dashboard \
--build-command 'npm ci && npm run build'
# Same repo later grows an API — one origin, no CORS
pandastack app create --name web \
--git-url https://github.com/acme/dashboard \
--build-command 'npm ci && npm run build' \
--start-command 'node server.js'The failures that waste an afternoon
- 404 on refresh. The SPA fallback is missing. It works when you navigate in-app because the router handles it client-side, and fails on a hard load because the server looks for a real file.
- Blank page, no errors, wrong asset paths. Your build assumed it is served from the domain root and it is being served from a subpath. Set Vite's `base` or CRA's `homepage` to match.
- Stale app after deploy. index.html got cached. Hashed assets should be cached aggressively and immutably; index.html should not be cached at all, because it is the file that points at the new hashes.
- Environment variable is undefined. It was added after the build, or without the VITE_/REACT_APP_ prefix. These are compile-time substitutions, not runtime lookups — changing one requires a rebuild, not a restart.
- Build works locally, fails on the platform with an out-of-memory error. Your laptop has 32 GiB and the builder has 1 GiB. Either raise the build memory or set NODE_OPTIONS to cap the old-space size below the limit.
The short version
Pure SPA, no backend: Cloudflare Pages or Netlify, and don't overthink it. Already deep in AWS: S3 and CloudFront. Docs or a demo: GitHub Pages. SPA plus an API you own, on one origin: Render, Railway, Fly, or PandaStack — with PandaStack being the one that keeps static deploys static and only runs a VM when your app actually needs one.
Frequently asked questions
Do I need SSR for a React app?
Only if you can name the reason. The two real ones are SEO for content that must be indexed — search engines do execute JavaScript, but rendering budgets are finite and inconsistent — and first-paint performance on slow devices where shipping and parsing a large bundle before anything appears is genuinely painful. Everything else usually points at a bundle-size problem rather than a rendering-strategy problem. Adopting SSR means adopting a server, a framework, and a hydration model, which is a large architectural change to make on a hunch.
Why does my React route 404 after refresh?
Because the server is doing exactly what it was told. Your router handles /settings client-side after the app loads, but a hard refresh asks the server for a file at that path, and no such file exists in the build output. The fix is a rewrite rule that returns index.html with a 200 status for any path that does not match a real file, letting the router take over once the app boots. Every host has a way to express this, and forgetting it is the most common React deployment bug in existence.
Can I hide an API key in a React app?
No — and this is worth being blunt about, because the framing invites clever workarounds that do not work. Anything in the bundle is downloadable by anyone who loads your page, obfuscation included, and build-time variables are substituted as literal strings before shipping. The only correct pattern is a server-side proxy: your React app calls your backend, your backend holds the credential and calls the third party. If you have already shipped a key in a bundle, rotate it now and assume it is compromised, because bots scan public bundles for exactly this.
Is a free static host good enough for production?
For a genuine SPA with no backend, frequently yes. The free tiers from the major static hosts are backed by real CDNs and will serve a small-to-medium application without complaint. What free tiers do not include is a support relationship, bandwidth guarantees during a traffic spike, and predictable behaviour once you exceed a build-minute or bandwidth quota. If the app makes money, paying the smallest paid tier buys you a plan that does not stop working the week you get attention.
Should I put the frontend and API on the same domain?
It removes a category of problems, so prefer it when you can. Same-origin means no CORS preflight requests, cookies that behave without SameSite workarounds, and no third-party-cookie exposure for auth. The cost is coupling: one deploy target, and a frontend change that requires redeploying whatever serves the API. The middle ground most teams land on is separate services with the API mounted on a path of the same domain through a proxy, which keeps deploys independent while the browser still sees one origin.
Keep reading
49ms p50 cold start. Fork, snapshot, and scale to zero.