Skip to main content

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

Updated 3 min readMarkdown
Refreshing a page on Vercel or Netlify gives a 404? Your single-page app needs a rewrite

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, _redirects must land in the published folder. On Vercel, vercel.json must 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.txt and sitemap.xml still 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.

No comments yet. Be the first to comment.