/lovable-issues

Fixing 404 Errors on Page Refresh in Lovable SPAs

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

Book a free  consultation
4.9
Clutch rating 🌟
600+
Happy partners
17+
Countries served
190+
Team members
Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free No-Code consultation

Why SPA Routing Fails on Refresh in Lovable Applications

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.

 

Why this happens (detailed)

 

  • Client-side routing vs. server requests: In an SPA the router maps /foo/bar inside the browser. On refresh the browser requests GET /foo/bar from the host. If the host doesn’t return index.html for that path, the app never boots into the expected route.
  • Static hosting behavior: Lovable’s Preview and Publish serve static files. If there’s no file at the requested path, the server returns a 404 (or a plain response) instead of serving index.html as a fallback. That’s a hosting behavior mismatch, not a JS bug.
  • Asset path and base href issues: Even when index.html is served, using relative asset paths (like ./static/js/app.js) or an incorrect can make nested routes look for assets at /foo/bar/static/... which 404s and breaks the app after refresh.
  • Preview vs exported deployment differences: The Lovable Preview UI may behave differently from an external host (Netlify, Vercel) that you later sync to via GitHub — assumptions that "it works locally" or "Preview behaves like the deploy" are common causes of surprise.
  • No CLI inside Lovable: Since Lovable has no terminal, anything that requires server configuration via CLI must be handled outside (GitHub export / external host). This constraint often leads people to assume they can change server routing as they would locally, but they can’t directly run that configuration from the Lovable editor.

 

Common symptoms you’ll see

 

  • Direct enter or refresh on a non-root route shows a 404 page or blank screen.
  • Console shows 404s for JS/CSS assets that use relative paths (paths include the route prefix).
  • Preview looks fine when navigating inside the app but deep links fail when opened in a new tab or after refresh.

 

Lovable prompt: add an explanation doc and a simple repro file

 

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>

 

Still stuck?
Copy this prompt into ChatGPT and get a clear, personalized explanation.

This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.

AI AI Prompt

How to Fix SPA Routing Issues on Refresh in Lovable

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.

 

React: Make a Chat edit to use HashRouter

 

Paste this into Lovable chat so Lovable updates your React entry file to use HashRouter (no hosting changes needed).

  • Change src/main.jsx or src/index.jsx (detect which exists) and replace BrowserRouter with HashRouter from react-router-dom. Then Preview and Publish.
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>)

 

Vue: Make a Chat edit to use Hash history

 

Paste this into Lovable chat so Lovable updates your Vue router config to use hash mode.

  • Change src/router/index.js or src/router.js to use createWebHashHistory instead of createWebHistory. Preview and Publish.
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 })

 

Static-host fallback files (Netlify or GitHub Pages)

 

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).

  • Create public/\_redirects for Netlify with a single rule.
  • Or create public/404.html for GitHub Pages that loads your SPA index.
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

  • If you need custom server rewrite rules (NGINX, Express), that requires modifying server config outside Lovable — use GitHub export/sync and edit host config via your hosting provider or terminal.
  • After any change in Lovable, always use Preview to confirm refresh behavior, then Publish or sync to GitHub for deployment.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Best Practices for Configuring SPA Routing in Lovable

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.

 

Key Best Practices (short)

 

  • Set a router basename or use HashRouter so your SPA knows its root when deployed to a subpath.
  • Make index.html base href and asset paths configurable via environment variable (store in Lovable Secrets).
  • Add concise redirect/rewrites files (_netlify/_redirects, vercel.json) in the repo so static hosts can serve index.html for app routes.
  • Prefer Hash routing for GitHub Pages or hosts you cannot configure.
  • Test with Lovable Preview and set Secrets in Lovable Cloud; use GitHub sync only if you must add platform-specific hosting config outside Lovable.

 

Concrete Lovable prompts to apply these best practices

 

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.

 

Notes & when to use GitHub export

 

  • If you need custom server-side config (Express, custom headers), export to GitHub and deploy from there — that part is outside Lovable (terminal or provider settings required).
  • Always Preview in Lovable after changing base/basename or switching to HashRouter to validate deep-link behavior before Publish.

 


Recognized by the best

Trusted by 600+ businesses globally

From startups to enterprises and everything in between, see for yourself our incredible impact.

RapidDev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with.

They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

Arkady
CPO, Praction
Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost.

He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Donald Muir
Co-Founder, Arc
RapidDev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space.

They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Mat Westergreen-Thorne
Co-CEO, Grantify
RapidDev is an excellent developer for custom-code solutions.

We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Emmanuel Brown
Co-Founder, Church Real Estate Marketplace
Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 

This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Samantha Fekete
Production Manager, Media Production Company
The pSEO strategy executed by RapidDev is clearly driving meaningful results.

Working with RapidDev has delivered measurable, year-over-year growth. Comparing the same period, clicks increased by 129%, impressions grew by 196%, and average position improved by 14.6%. Most importantly, qualified contact form submissions rose 350%, excluding spam.

Appreciation as well to Matt Graham for championing the collaboration!

Michael W. Hammond
Principal Owner, OCD Tech

We put the rapid in RapidDev

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.Â