Skip to content

Netlify and Vercel deploy error404 "Page not found" when you refresh a page or open a link

The home page loads and clicking around works, but refreshing /dashboard or opening a shared link shows the host’s 404 page. The app is fine. The host doesn’t know to send every path to it. Here’s the one rule that fixes it, or hand it over at a fixed price.

Short answer

Your app is a single-page app: one index.html that handles every route in the browser. When you refresh /dashboard, the host looks for a file at that path, finds none and returns 404. Add a rewrite that serves index.html for every path: a _redirects file on Netlify, or a vercel.json rewrite on Vercel.

The fix for each host

  1. 01

    Netlify: no rewrite to index.html

    Netlify’s docs give one rule for single-page apps. Put it in a file named _redirects, with no extension, in your publish folder. In a Vite project (the default for Lovable and many Bolt apps; look for a vite.config file), save it as public/_redirects: Vite copies public/ into the root of dist, so it ships with every build. Real files such as images and scripts still load, because the rule doesn’t override files that exist.

    # public/_redirects
    /*    /index.html   200
  2. 02

    Vercel: no rewrite in vercel.json

    Vercel’s Vite guide says deep linking won’t work out of the box for a single-page app. Add a vercel.json at the root of the project with a rewrite to index.html, then redeploy.

    {
      "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
    }
  3. 03

    The rule exists but never ships

    Unless your repository root is also the publish directory, a _redirects file at the root isn’t published, so Netlify never sees it. Check that the publish directory is your build output folder (dist for a default Vite app) and that _redirects is inside it after the build. Some build tools skip files whose names start with an underscore, so look in dist to be sure. On Vercel, vercel.json has to sit at the project root, the folder set as the project’s root directory.

Checked against the vendor’s docs on : Netlify docs: Rewrites and proxies (history pushstate and single-page apps); Netlify docs: Redirects and rewrites; Vercel docs: Vite on Vercel; Vite docs: The public directory.

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: Bolt or Lovable build fails on deploy · Lovable, Bolt and Replit app fixes

Questions

More on this error

Won’t every wrong URL now show my app instead of a 404?

Yes, the host now sends every path to the app, so the app has to show its own not-found screen. Add a catch-all route at the end of your router that renders a "Page not found" view.

Why does only the home page work after a refresh?

The home page is the one route that matches a real file: index.html at the root. Every other route exists only inside the app’s JavaScript, so the host has no file to serve until you add the rewrite.

Does the rewrite break my API routes or images?

On Netlify, a normal 200 rewrite doesn’t override files that exist. On Vercel, check your /api routes still respond after adding the rewrite. API routes on another domain aren’t affected. If you proxy an API path through the same host, list that rule above the catch-all, because rules apply in order.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; we reply by email, usually within one business day.