Explore why SPA routing fails on refresh in Lovable apps, discover essential fixes, and learn best practices for seamless SPA configuration.

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Because a Single‑Page App (SPA) relies on the client to interpret routes, a browser refresh makes the browser ask Lovable’s static host for that exact path — and Lovable’s preview/asset server does not automatically hand every unknown path back to your app’s index.html. That server response (404 or a different file) or mismatched asset paths causes the client router to never initialize for that URL, so the route fails on refresh.
Paste the prompt below into Lovable chat to create a small in-repo explanation and a test page you can open directly to observe how the host handles a deep link. This is diagnostic only — it documents the cause and helps reproduce the server-side behavior without changing server routing.
// Create a new file docs/WHY_SPA_REFRESH.md with this content
// The file explains why SPA refreshes fail and how to reproduce the symptom in Preview.
Create file docs/WHY_SPA_REFRESH.md with the following content:
# Why SPA routing fails on refresh in this project
This document explains why refreshing a client-side route can fail in Lovable Preview/Publish.
- SPAs use client-side routing. A browser refresh requests the same path from the static server.
- If the server does not return index.html for unknown paths, the SPA never initializes for that URL.
- Relative asset paths can make nested routes request assets from wrong locations, causing 404s.
How to reproduce in Preview:
- Open Preview for the app root.
- Manually change the browser URL to /some/deep/route and press Enter.
- Observe whether the server returns a 404 or the app fails to load.
(Do not change server configuration in this project from Lovable — this doc is diagnostic.)
// Create a simple static test page to demonstrate the behavior.
// This file is not a fix — it's a reproducible artifact you can open directly.
Create file public/preview-refresh-test.html with the following content:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Preview refresh test</title>
</head>
<body>
<h1>Preview refresh test</h1>
<p>This page exists at /preview-refresh-test.html. Opening it directly proves the host will serve this file.</p>
<p>Now try navigating in the browser to <code>/non-existent-route</code> and refresh — if you get a 404 or different content, the host is not returning index.html for unknown paths.</p>
</body>
</html>
This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.
Use a client-side fallback that doesn’t rely on server rewrites (most reliable inside Lovable) or add a static redirect fallback file for your static host. The quickest fix inside Lovable is to switch your app to hash-based routing (React: HashRouter, Vue: createWebHashHistory), or create a public/_redirects (Netlify) or public/404.html (GitHub Pages) so refreshes serve index.html. Below are pasteable Lovable chat prompts that will edit files, add redirect files, and guide you to Preview/Publish.
Paste this into Lovable chat so Lovable updates your React entry file to use HashRouter (no hosting changes needed).
Please edit the React entry file in the project.
- If src/main.jsx exists, update it. Otherwise update src/index.jsx.
- Replace any usage of <BrowserRouter> (imported from 'react-router-dom') with <HashRouter>.
- Update imports: import { HashRouter } from 'react-router-dom' instead of BrowserRouter.
- If routes are defined in src/App.jsx or similar, keep them unchanged—only the outer router wrapper changes.
- After making the change, run Lovable Preview and confirm navigation works on refresh. Then Publish.
Example change to perform inside src/main.jsx:
// Before:
// import { BrowserRouter } from 'react-router-dom'
// ReactDOM.createRoot(...).render(<BrowserRouter><App/></BrowserRouter>)
// After:
// import { HashRouter } from 'react-router-dom'
// ReactDOM.createRoot(...).render(<HashRouter><App/></HashRouter>)
Paste this into Lovable chat so Lovable updates your Vue router config to use hash mode.
Please edit the Vue router file.
- Open src/router/index.js (or src/router.js if present).
- Replace createWebHistory(...) with createWebHashHistory(...).
- Keep existing routes the same.
- After the change, Preview in Lovable to confirm refreshes work, then Publish.
Example change inside src/router/index.js:
// Before:
// import { createRouter, createWebHistory } from 'vue-router'
// const router = createRouter({ history: createWebHistory(), routes })
// After:
// import { createRouter, createWebHashHistory } from 'vue-router'
// const router = createRouter({ history: createWebHashHistory(), routes })
If you must keep BrowserRouter, add a static fallback so the host serves index.html for unknown paths. Paste the appropriate prompt into Lovable to create these files in the public/ folder, then Preview and Publish (or sync to GitHub if you deploy elsewhere).
Please create public/_redirects with the following content (Netlify):
/* /index.html 200
// This ensures all routes are served index.html so SPA handles routing
Please create public/404.html with a simple fallback for GitHub Pages:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Redirecting…</title>
<meta name="viewport" content="width=device-width">
</head>
<body>
<script>
// Try to load the single-page app index preserving the URL
window.location.replace(window.location.pathname + window.location.search + window.location.hash);
</script>
</body>
</html>
// Place this as public/404.html and Preview/Publish. GitHub Pages will serve it on unknown routes.
Notes
Use explicit router bases, prefer hash routing when you can’t control the static host, make asset paths relative or configurable, add simple platform redirect/rewrites files in the repo, store route/base values in Lovable Secrets, and always validate with Lovable Preview before Publish or GitHub sync. These steps make routing predictable across Lovable Cloud Preview/Publish and common static hosts without needing a terminal.
Lovable, make these code changes for a React SPA using react-router (Vite or CRA):
- Update file: src/main.jsx (or src/index.jsx)
* Wrap app with BrowserRouter and read basename from env:
// import statements...
import { BrowserRouter } from "react-router-dom";
// ...
<BrowserRouter basename={process.env.REACT_APP_BASE_PATH || "/"}>
<App />
</BrowserRouter>
- Update file: public/index.html
* Ensure there's a <base> element that reads PUBLIC_URL if available:
// inside <head>...
<base href="%PUBLIC_URL%/" />
// For Vite, set <base href="/" /> and we will manage via env at build time.
- Create file: public/_redirects
* Add this single line to support many static hosts:
// Netlify-style fallback
/* /index.html 200
Also include a short commit message: "router: add basename + base href + _redirects"
Lovable, if you prefer hash routing (good for immutable static hosts like GitHub Pages), change the router:
- Update file: src/main.jsx (or src/index.jsx)
* Replace BrowserRouter with HashRouter:
// import statements...
import { HashRouter } from "react-router-dom";
// ...
<HashRouter>
<App />
</HashRouter>
Commit message: "router: switch to HashRouter for static-host compatibility"
Lovable, create platform-specific light config files in repo so hosting can map all routes to index.html:
- Create vercel.json at project root:
{
// rewrites to serve index.html for any route
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}
- (Optional) Create netlify.toml if you prefer TOML:
[build]
publish = "public"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Commit message: "hosting: add vercel/netlify rewrite fallbacks"
Lovable, configure env secrets for base path and public URL in Lovable Cloud:
- Use Lovable Secrets UI to create:
* REACT_APP_BASE_PATH = /your-subpath // used by BrowserRouter basename
* PUBLIC_URL = /your-subpath // used in index.html base href (CRA)
- After adding secrets, Preview the app in Lovable to confirm routes render correctly.
From startups to enterprises and everything in between, see for yourself our incredible impact.
Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.Â