Single-page apps (SPAs) built with React, Vue, Angular, Svelte or Vite compile to static files and run entirely in the browser, so they host well on cPanel. The classic problem: the home page works, but refreshing /dashboard or opening a shared deep link returns 404 Not Found. The fix is one .htaccess rule.
Before you start
- Build the app on your computer:
npm run build. Output is usuallydist/(Vite, Vue) orbuild/(Create React App); Angular usesdist/<project>/browser. - Decide where it lives: the domain root, a subfolder such as
/app, or a subdomain likeapp.example.com(create a subdomain).
Set the base path before building
| Framework | Setting for a subfolder /app/ |
|---|---|
| Vite (React, Vue, Svelte) | base: '/app/' in vite.config |
| Create React App | "homepage": "/app" in package.json |
| Vue Router | createWebHistory('/app/') |
| React Router | <BrowserRouter basename="/app"> |
| Angular | ng build --base-href /app/ |
For the domain root or a subdomain, keep the default /.
Upload the build
- Zip the contents of the build folder.
- In File Manager, open the target folder (
public_html,public_html/appor the subdomain's document root), upload and extract the ZIP. - Make sure
index.htmlsits directly in that folder.
Add the fallback rule
Create or edit .htaccess in the same folder as index.html (enable Show Hidden Files in File Manager settings):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>For a subfolder, change RewriteBase / to RewriteBase /app/ and the last line to RewriteRule . /app/index.html [L].
Real files (JS, CSS, images) are served normally; every other path loads index.html, and the router in your app shows the right page.
Tip: Do not cache index.html for long, or visitors keep an old version after you deploy. Hashed asset files can be cached for a year; see static site caching.
Calling an API
- If the API is on another domain, it must send CORS headers allowing your app's origin.
- Keep secret API keys out of the front-end build; anything in the bundle is public.
- A small backend can run on the same account as a Node.js app or PHP.
Troubleshooting
- Blank page, console shows 404 for JS files: wrong base path; rebuild with the correct setting.
- Still 404 on refresh: the
.htaccessis in the wrong folder, the file name lacks the dot, or a parent.htaccess(for example WordPress in the root) catches the request first. - 500 error: typo in
.htaccess; see fix 500 errors.
