Refreshing a page on Vercel or Netlify gives a 404? Your single-page app needs a rewrite
Serve index.html for app routes, keep a real not-found screen

Clicking through the app is fine. Refreshing /dashboard, or opening it from a bookmark, isn't:
404: NOT_FOUND
Page not found
Cannot GET /dashboard
Routes like /dashboard only exist inside the JavaScript running in the browser. When the page is refreshed, the request goes to the host, the host looks for a file at that path, and there isn't one. So it answers 404 before the app gets a chance to load. Tell the host to serve index.html for app routes and the problem goes away.
This is one of the first things that breaks when a Lovable or Bolt app leaves the builder's hosting.
Three usual causes
- The host has no rewrite at all. Lovable's own hosting does this automatically; Vercel, Netlify and storage buckets don't.
- The rule is in a file the host never reads. On Netlify,
_redirectsmust land in the published folder. On Vercel,vercel.jsonmust be at the project root. - The rule redirects instead of rewriting. A 301 changes the URL or loops; you want a 200 rewrite.
Confirm it
Paste a deep link such as /dashboard into a fresh tab. A host 404 that appears before any of your app loads means the rewrite is missing. Then look for vercel.json at the root, or _redirects in the deployed files.
Vercel
At the project root, vercel.json:
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}
Redeploy.
Netlify
Put the rule in public/_redirects, which Vite copies into the build output:
/* /index.html 200
Redeploy. The trailing 200 is the part that makes it a rewrite.
Don't lose real 404s
With the rewrite in place the host never says 404 again, so your app has to. Add a catch-all route that renders a "page not found" screen for addresses that don't exist.
How to know it worked
- Several deep links, refreshed, each show the right screen.
- An address you made up shows your app's not-found screen.
- Images,
robots.txtandsitemap.xmlstill load as files.
Keeping it fixed
Commit the rule to the repository rather than setting it only in a dashboard, and test deep links on any new host before the domain points at it.
One note on SEO: the rewrite fixes the 404, not search. A client-rendered app gives crawlers little to read either way; pre-rendering key pages is the separate fix if search traffic matters.
Docs: Vercel rewrites and Netlify rewrites and proxies.
The original guide is on our site: Your app shows 404 when you refresh a page after deploying. Before a host move, the free Launch Check can catch other launch problems on the live app.
About the author
- Founder and CEO of StacksMesh (stacksmesh.com). We fix, launch and migrate apps built with Base44, Lovable, Bolt and Replit, with a fixed price in writing before any work. I write about making AI-built apps safe and production-ready.
Comments
Join the discussionNo comments yet. Be the first to comment.
