/lovable-issues

Resolving Routing Issues in Lovable with React Router

Discover why route configurations break in Lovable and master React Router setup with essential best practices for a seamless experience.

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 Route Configurations Break in Lovable With React Router

Routes break in Lovable with React Router because the app’s router configuration (base path, router type, and asset/publicPath expectations) usually assumes a local dev server root and filesystem behavior that Lovable’s preview and published hosting don’t exactly match. That mismatch — especially BrowserRouter’s implicit “/” root, missing index.html fallback rewrites, and build-time PUBLIC_URL/basename differences — is the most common root cause. Other frequent problems are absolute paths, environment-variable assumptions, and lazy/dynamic route loading that expects a local dev server.

 

Why this happens (detailed causes)

 

  • BrowserRouter basename vs Lovable preview path: Lovable’s preview or deployed URL can be nested or served from a non-root path. If your Router assumes "/" but the app runs under /workspace/... or another subpath, routes won’t resolve and refreshes 404.
  • No index.html fallback / hosting rewrite: On refresh or direct navigation to a client route, static hosts need to rewrite to index.html. Locally dev servers do this automatically; the preview/publish environment may not, causing 404s.
  • PUBLIC_URL / build publicPath mismatch: Build-time variables (PUBLIC_URL, homepage, or bundler publicPath) determine where assets and route basenames resolve. Lovable’s build environment can differ from your local dev environment if those env vars aren’t set in Lovable Cloud.
  • Absolute vs relative links: Hard-coded absolute links ("/foo") assume root. If the deployed path is different, the links break. Relative links behave differently depending on Router setup and base href.
  • Code-splitting and lazy loading assumptions: Dynamic chunks loaded by path (e.g., expecting dev server to serve /static/js/…) can break if build output paths differ or publicPath is wrong.
  • Using MemoryRouter or server-only routing in an SSR build: Confusion between client-only routing and SSR/SSG setups can cause unexpected behavior when previewing the static build.
  • Environment/config drift: Locally set env vars, aliases, or build scripts that aren’t mirrored into Lovable Cloud (Secrets/Env) will change how routes or imports resolve.

 

Lovable prompts to diagnose where it’s breaking (paste into Lovable chat)

 

Please scan the repository and create a diagnostics file at diagnostics/react-router-analysis.md.

Tasks:
- Open these files if they exist and report exact code snippets and lines:
  - src/index.tsx or src/main.jsx (where <BrowserRouter>, <HashRouter>, or <RouterProvider> is mounted)
  - src/App.tsx or src/App.jsx (the <Routes> block and any use of basename)
  - public/index.html (check <base href="...">)
  - package.json (homepage, build scripts)
  - vite.config.ts or webpack.config.js (check base/publicPath settings)
  - Any environment files (.env, .env.production) used by the build
- For each file, write whether a basename/publicPath/PUBLIC_URL is set and exact values.
- Detect if routes use absolute paths (strings starting with "/") or relative paths.
- Detect use of HashRouter, MemoryRouter, or BrowserRouter.
- List dynamic imports/lazy-loaded routes and where chunk files expect to be served from (based on config).
- Summarize the most likely single cause(s) this repo will hit when previewing or publishing in Lovable.

Create diagnostics/react-router-analysis.md with the findings and a clear explanation of why each finding will cause route breakage in Lovable’s preview/publish environment. Do not change source files yet — only produce the analysis.

 

After analysis, please open the app in Lovable Preview and attempt loading these paths, then capture whether the app renders or returns a 404:
- /
- /a known client route (list the route you found in src/App.tsx)
- Refresh the known client route (simulate direct navigation / refresh) and report the result.

Save the results to diagnostics/preview-route-check.md with timestamps and the exact preview URL used.

 

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 Set Up React Router Correctly in Lovable

Use a client-side router that doesn’t require server rewrites by default in Lovable: wrap your root app with a router (I recommend HashRouter in Lovable), ensure your route tree uses react-router-dom v6 (Routes / Route), replace internal <a href=...> with react-router-dom Link, and add react-router-dom to package.json. Below are ready-to-paste Lovable prompts that will make those edits for you.

 

Lovable prompt — Wrap your app with HashRouter (safe, no server changes)

 

Please update the project to use HashRouter so client routing works in Lovable without server rewrite rules.

Find the entry file (check in order and edit the first that exists):
- src/main.tsx
- src/main.jsx
- src/index.tsx
- src/index.jsx

For the file you find, replace the root render so the app is wrapped with HashRouter from 'react-router-dom'.

// Example for TypeScript (src/main.tsx or src/index.tsx)
// If your project is JavaScript, apply the same edits in the JSX file.

Update the file at src/main.tsx to:

import React from 'react';
import { createRoot } from 'react-dom/client';
import { HashRouter } from 'react-router-dom'; // // add this import
import App from './App';
import './index.css';

// // wrap the app with HashRouter
const root = createRoot(document.getElementById('root')!);
root.render(
  <React.StrictMode>
    <HashRouter>
      <App />
    </HashRouter>
  </React.StrictMode>
);

If your entry file is src/main.jsx / src/index.jsx, do the equivalent imports and wrapping. If a file already imports BrowserRouter, replace it with HashRouter.
Also update package.json to include "react-router-dom": "^6" if it's missing (see next prompt for package.json edit instructions).

 

Lovable prompt — Convert internal anchor links to Link

 

Please scan the src/ directory and replace internal anchor tags that cause full page reloads.

Rules:
- Replace occurrences of <a href="/..."> and <a href="#..."> that are meant for internal navigation with <Link to="..."> from 'react-router-dom'.
- Add "import { Link } from 'react-router-dom';" at the top of each modified file if not present.
- Preserve external links (href starting with http:// or https://) and mailto: / tel: links — do not change those.
- Do not change anchors used for simple fragment scrolling unless they are intended to drive app routes.

Example replacement (for Lovable to perform):
// Before
import React from 'react';
export default function Nav() {
  return <nav><a href="/about">About</a></nav>;
}

// After
import React from 'react';
import { Link } from 'react-router-dom'; // // added import
export default function Nav() {
  return <nav><Link to="/about">About</Link></nav>;
}

Please apply these replacements automatically across src/ and create a short report listing changed files.

 

Lovable prompt — Add react-router-dom to package.json (you will need to install deps outside Lovable)

 

Please open package.json and ensure there is a dependency entry:
"react-router-dom": "^6"

If it's missing, add it under "dependencies". Example snippet:

"dependencies": {
  // // existing deps...
  "react-router-dom": "^6"
}

Note: Lovable cannot run npm/yarn installs from inside the editor. After this edit, either:
- Use your GitHub sync or export the repo and run `npm install` or `yarn` locally or in your CI (outside Lovable — terminal required), or
- If your project builds in a CI pipeline connected to GitHub, push these package.json changes and let CI install deps.

Add a short message in Lovable confirming which option you will use to install.

 

Optional Lovable prompt — Switch to BrowserRouter for pretty URLs (requires server rewrite; outside Lovable)

 

If you prefer BrowserRouter (clean URLs), please update the entry file to use BrowserRouter instead of HashRouter.

However, BrowserRouter requires the hosting server to redirect all paths to index.html (SPA fallback). Lovable cannot modify server hosting rules from the editor. If you want BrowserRouter:
- Change HashRouter to BrowserRouter in the entry file.
- Add/update package.json as above.
- Then export or sync to GitHub and configure your hosting (GitHub Pages, Netlify, Vercel, or your server) to add a SPA fallback rewrite rule (outside Lovable — terminal/hosting UI required).

Please implement the code change and add a note that server rewrite will be configured outside Lovable.

 

  • After these edits: Use Lovable Preview to validate navigation works (HashRouter should work immediately). If you chose BrowserRouter, remember the external hosting rewrite step is required.
  • If you want, tell Lovable to run a repo-wide search for "href=" and show a diff before applying replacements — that’s safe and very helpful.

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 Setting Up React Router in Lovable

Use a Router with a deliberate basename, prefer a safe fallback (HashRouter) when you can't control static-host rewrites, read the base path from an env variable set in Lovable Secrets, lazy-load routes with Suspense, provide a catch-all route, and always test via Lovable Preview before Publish or GitHub export.

 

Concrete Lovable prompts you can paste (step-by-step)

 

  • Prompt — set Router wrapper and basename (auto-detect Vite vs CRA)
    Paste this into Lovable Chat Mode and ask it to update the entry file (check both src/main.tsx and src/index.tsx and update the one that exists):
// Edit the app entry file. Check src/main.tsx or src/index.tsx and update the Router wrapper.
// If both exist, update src/main.tsx.
// Replace the existing root render so the app uses BrowserRouter with a basename pulled from env.

/// File: src/main.tsx  // or src/index.tsx if that file exists
import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

// // Try Vite style env first, then CRA style, then default to '/'
const base =
  (typeof import.meta !== 'undefined' && import.meta.env?.VITE_BASE_PATH) ||
  process.env.REACT_APP_BASE_PATH ||
  '/';

createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <BrowserRouter basename={base}>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

 

  • Prompt — route organization, lazy loading, catch-all, and scroll restore
    Paste this into Lovable Chat Mode and ask it to edit src/App.tsx (or src/App.jsx) replacing the block with the pattern below:
// Edit src/App.tsx (or src/App.jsx) and replace the routes area.
// Use React Router v6 patterns: lazy, Suspense, nested routes, and a '*' catch-all.

import React, { Suspense, lazy } from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';

// // lazy-load route pages
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
const NotFound = lazy(() => import('./pages/NotFound'));

export default function App() {
  return (
    <Suspense fallback={<div>Loading…</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="about" element={<About />} />
        {/* // catch-all that shows NotFound or redirects */}
        <Route path="*" element={<NotFound />} />
      </Routes>
    </Suspense>
  );
}

 

  • Prompt — if you cannot configure host rewrites in production, switch to HashRouter
    Paste this into Lovable Chat Mode and ask it to edit the same entry file used above to import HashRouter instead of BrowserRouter (one-line change):
// Edit src/main.tsx (or src/index.tsx) and replace BrowserRouter import with HashRouter
import { HashRouter } from 'react-router-dom';
// ...
<HashRouter>
  <App />
</HashRouter>

 

  • Prompt — create or update environment variable in Lovable Secrets UI
    Ask Lovable to open the project's Secrets UI and create a variable used by the app. Example instruction for Lovable to perform:
// In Lovable Secrets UI: create a secret / env var.
// Key: VITE_BASE_PATH  // use REACT_APP_BASE_PATH for CRA apps
// Value: /my-app-base   // or "/" for root
// Make it available to Preview and Publish (expose to preview if you want to test Preview with the base path)

 

  • Prompt — add static-host rewrite file if you control deploy via repo
    If you plan to deploy to Netlify or Vercel from the GitHub-exported repo, paste this into Lovable and ask it to create the correct file(s):
// Create netlify.toml at repo root (for Netlify SPA rewrite)
[build]
  publish = "dist" // adjust to your build output

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

 

Practical tips and why these are the best practices

 

  • Always control basename via env so Preview/Publish and production use the same routing root. Set it in Lovable Secrets UI and read it in code (Vite uses VITE\__, CRA uses REACTAPP_).
  • Use HashRouter as a safe fallback when you can't guarantee server rewrites — it works without any host configuration and is easiest to preview from Lovable.
  • Provide a catch-all route to show a NotFound component or redirect; otherwise direct navigations will break when host rewrites aren't set.
  • Lazy-load pages and test in Preview — Lovable Preview exercises the in-app navigation. Use Preview to click links and then Publish or export to GitHub if you need host-specific config files (netlify.toml, vercel.json).
  • When you need host rewrites/config outside Lovable, add rewrite files in the repo with a Chat Mode edit, then use GitHub export/sync and configure the target host — no terminal required inside Lovable.


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.