SPA fallback routing makes every URL in your Lovable app serve index.html so React Router can handle the path client-side. Without it, directly visiting /dashboard or refreshing any page returns a server 404. Configure it by adding vercel.json with rewrites for Vercel, a _redirects file for Netlify, or a catch-all route in your React Router setup for Lovable's built-in hosting.
Why pages return 404 when accessed directly in deployed Lovable apps
Lovable projects are Single Page Applications (SPAs). The entire app is a single HTML file (index.html) that uses JavaScript to render different pages based on the URL. When you click a link inside the app, React Router intercepts it and swaps the content without a server request. This works seamlessly. The problem appears when someone types a URL directly into the browser address bar (like yourdomain.com/dashboard) or refreshes the page. The browser sends a request to the server asking for /dashboard. The server looks for a file or folder called 'dashboard' — it does not exist because there is only index.html. The server returns a 404 error. The fix is a fallback rule that tells the server: 'For any URL that does not match a real file, serve index.html instead.' React Router then reads the URL and renders the correct page. Lovable's built-in hosting at lovable.app handles this automatically, but any external host (Vercel, Netlify, Cloudflare Pages) needs explicit configuration.
- No SPA fallback rule configured on the hosting platform — the server returns 404 for client-side routes
- vercel.json or _redirects file missing from the project — the host has no fallback instructions
- Fallback file placed in the wrong directory — it must be in /public so it gets included in the build output
- Custom 404 page intercepts all routes instead of just truly missing ones
- Hosting platform auto-detects the wrong framework and applies incorrect routing rules
Error messages you might see
404 - Page Not Found (on Vercel after deployment)Vercel cannot find a file for the requested path. Add a vercel.json file with a rewrite rule that sends all requests to /index.html.
Page Not Found - Looks like you've followed a broken link (Netlify)Netlify's default 404 page appears because no _redirects file exists. Create a _redirects file in /public with the rule: /* /index.html 200.
Cannot GET /dashboardThe development server or hosting platform has no fallback rule. This is the raw server response when no file matches the requested path.
Before you start
- A Lovable project that uses React Router for client-side navigation
- Knowledge of which hosting platform you are deploying to (Vercel, Netlify, Cloudflare Pages, or Lovable's built-in hosting)
- Access to your project files via Dev Mode or GitHub
How to fix it
Add a vercel.json file for Vercel deployments
Vercel needs an explicit rewrite rule to route all paths to index.html for SPAs
Add a vercel.json file for Vercel deployments
Vercel needs an explicit rewrite rule to route all paths to index.html for SPAs
Create a file called vercel.json in your project root (the same level as package.json). Add a rewrites array with a single rule that matches all paths and serves index.html. This tells Vercel that every URL should be handled by your SPA, not by the server's file system. Place this file in the project root, not in /public — Vercel reads it from the repository root.
1{2 "rewrites": [3 {4 "source": "/(.*)",5 "destination": "/index.html"6 }7 ]8}Expected result: All paths on Vercel serve index.html. React Router handles the URL and renders the correct page.
Add a _redirects file for Netlify deployments
Netlify uses a _redirects file in the build output directory to configure routing rules
Add a _redirects file for Netlify deployments
Netlify uses a _redirects file in the build output directory to configure routing rules
Create a file called _redirects (no file extension) inside the /public folder of your project. Add a single line: /* /index.html 200. The 200 status code is important — it tells Netlify to serve index.html as a success response, not as a redirect. If you use a 301 or 302 instead, the URL in the browser changes to /index.html, which breaks your routing.
1/* /index.html 200Expected result: All paths on Netlify serve index.html with a 200 status. Direct URL access and page refreshes work correctly.
Add a custom 404 page in React Router as a catch-all
Even with SPA fallback, you need a catch-all route for URLs that do not match any defined page
Add a custom 404 page in React Router as a catch-all
Even with SPA fallback, you need a catch-all route for URLs that do not match any defined page
In your App.tsx Routes, add a Route with path='*' at the end of your route list. This catches any URL that does not match a defined route and renders your custom 404 component. Without this, unmatched URLs show a blank page because React Router has no component to render.
<Routes> <Route path="/" element={<Index />} /> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/settings" element={<Settings />} /></Routes>import NotFound from "./pages/NotFound";<Routes> <Route path="/" element={<Index />} /> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/settings" element={<Settings />} /> {/* Catch-all for undefined routes */} <Route path="*" element={<NotFound />} /></Routes>Expected result: Visiting an undefined URL like /xyz shows your custom 404 page instead of a blank screen or server error.
Create a user-friendly NotFound page component
A helpful 404 page tells users they are on a wrong URL and gives them a way to navigate back to working pages
Create a user-friendly NotFound page component
A helpful 404 page tells users they are on a wrong URL and gives them a way to navigate back to working pages
Create a simple NotFound page component that explains the page does not exist and provides navigation back to the home page. Keep it clean with Tailwind styling to match the rest of your app. If your project has a complex routing setup with protected routes, nested layouts, and custom 404 pages for different sections, RapidDev's engineers have built these patterns across 600+ Lovable projects.
1import { Link } from "react-router-dom";23export default function NotFound() {4 return (5 <div className="flex flex-col items-center justify-center min-h-screen p-8">6 <h1 className="text-4xl font-bold mb-4">404</h1>7 <p className="text-muted-foreground mb-6">This page does not exist.</p>8 <Link to="/" className="text-primary hover:underline">9 Go back to the home page10 </Link>11 </div>12 );13}Expected result: A clean 404 page appears for any undefined route, with a link to navigate back to the home page.
Complete code example
1import { Link, useLocation } from "react-router-dom";23export default function NotFound() {4 const location = useLocation();56 return (7 <div className="flex flex-col items-center justify-center min-h-screen p-8 text-center">8 <div className="max-w-md">9 <h1 className="text-6xl font-bold text-primary mb-4">404</h1>10 <h2 className="text-xl font-semibold mb-2">Page not found</h2>11 <p className="text-muted-foreground mb-6">12 The page <code className="bg-muted px-2 py-1 rounded text-sm">{location.pathname}</code> does not exist.13 </p>14 <div className="flex gap-4 justify-center">15 <Link16 to="/"17 className="inline-flex items-center px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors"18 >19 Go home20 </Link>21 <button22 onClick={() => window.history.back()}23 className="inline-flex items-center px-4 py-2 border border-input rounded-md hover:bg-accent transition-colors"24 >25 Go back26 </button>27 </div>28 </div>29 </div>30 );31}Best practices to prevent this
- Always add a vercel.json or _redirects file before deploying to an external host — do not wait for the 404 to happen
- Place _redirects inside the /public folder so Vite copies it to the dist/ build output automatically
- Place vercel.json in the project root (not in /public) since Vercel reads it from the repository root
- Use status code 200 (not 301 or 302) in Netlify _redirects to prevent the URL from changing to /index.html
- Always add a catch-all Route (path='*') as the last route in your React Router configuration
- Test fallback routing by visiting a deep URL directly (like /settings/profile) in an incognito window after deployment
- Lovable's built-in hosting at lovable.app handles SPA fallback automatically — you only need configuration for external hosts
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I deployed my Lovable.dev project to [Vercel/Netlify/Cloudflare Pages] and pages return 404 when I access them directly or refresh the page. The app works fine when I navigate inside the app, but direct URLs fail. Here is my deployment setup: - Hosting platform: [Vercel/Netlify/etc.] - Build command: npm run build - Output directory: dist - My vercel.json or _redirects file: [paste it or say 'none'] Please help me: 1. Create the correct fallback configuration for my hosting platform 2. Explain where to place the file 3. Create a 404 catch-all route in React Router 4. Explain why this happens with SPAs
My deployed app shows 404 when I access pages directly by URL. Create a vercel.json file in the project root with SPA rewrite rules. Also create a _redirects file in /public for Netlify compatibility. Add a catch-all Route in @src/App.tsx that renders a custom NotFound page. Create the NotFound page in @src/pages/NotFound.tsx with a link back to the home page.
Frequently asked questions
What is SPA fallback routing?
SPA fallback routing tells a web server to serve index.html for any URL that does not match a real file. This allows React Router (which runs in the browser) to read the URL and display the correct page. Without it, the server returns 404 for any path other than the root.
Why do pages work in Lovable's preview but 404 after deployment?
Lovable's preview environment has built-in SPA fallback support. External hosting platforms like Vercel and Netlify do not enable this by default. You need to add a vercel.json or _redirects file to configure the fallback.
Where do I put the _redirects file for Netlify?
Place it in the /public folder of your Lovable project. Vite automatically copies everything in /public to the dist/ build output. Netlify reads the _redirects file from the root of the deployed directory.
Where do I put vercel.json?
Place vercel.json in the project root directory, at the same level as package.json. Do not put it in /public — Vercel reads configuration files from the repository root, not from the build output.
Does Lovable's built-in hosting need SPA fallback configuration?
No. When you publish to lovable.app using the Publish button, SPA fallback routing is handled automatically. You only need to configure it when deploying to external platforms like Vercel, Netlify, or Cloudflare Pages.
What is the difference between a rewrite and a redirect?
A rewrite serves a different file while keeping the URL the same (the user sees /dashboard). A redirect changes the URL in the browser (the user sees /index.html). For SPA routing, always use a rewrite (status 200) not a redirect (status 301/302).
What if I can't fix this myself?
If your deployment involves complex routing rules, multiple domains, or mixed static and dynamic pages, RapidDev's engineers have configured SPA fallback routing across 600+ Lovable projects on every major hosting platform.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your issue.
Book a free consultation