All guidesMore providers: databases, auth, hosting, email and payments
On this page

Netlify question

Netlify

Why does my Vite or React app show "Page not found" on Netlify when I refresh?

By Ohad Krispin, founder of VibeRaven · LinkedIn

A Vite or React single-page app shows Netlify's "Page not found" on refresh because a route such as /dashboard exists only in your JavaScript router, and Netlify finds no file at that path in the published folder. Netlify says a single-page app that uses history pushState must add a rewrite rule that serves index.html no matter what URL the browser requests. Put the line /* /index.html 200 in a _redirects file in the publish directory, or the same rule in netlify.toml. In a Vite app, save the file as public/_redirects so the build copies it into dist. Reproduced with vite 5.4.21 on 2026-10-31.

Where does the _redirects file go in a Vite app?

Netlify says to save a plain text file called _redirects, with no file extension, to the publish directory of your site, and that when you use a build command the file should end up in the folder you deploy. Vite copies the files in its public directory to the root of dist as they are. In a local run with vite 5.4.21, a build with public/_redirects produced dist/_redirects holding the rule, and a build without that file produced a dist folder with only index.html and assets. For a Vite project, Netlify suggests npm run build as the build command and dist as the publish directory.

# public/_redirects
/*  /index.html  200

Can I use netlify.toml instead of a _redirects file?

Yes. Netlify documents the same rewrite as a redirect in netlify.toml, and says the rule should be the last redirect or rewrite you list. The engine reads rules from top to bottom and uses the first match, with rules in _redirects processed before rules in netlify.toml, so a catch-all placed early would match before the rules below it. One rule in one place is enough.

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

The rule is in place and I still get Page not found

Check the published folder first. Netlify's error reference gives a missing index.html as the most common reason for a page not found error, so run npm run build locally and confirm dist/index.html and dist/_redirects exist, and that the Publish directory in the site settings is dist. Then remember that Netlify serves a file that exists at the path before it applies a rewrite, so the catch-all leaves scripts and images alone; adding ! after the status code (200!) makes a rule win even when a file matches.

If the page loads after the rewrite but a script fails after a deploy, Netlify warns that code splitting and hashed filenames can break asset references with atomic deploys, and shows an "Uncaught SyntaxError: Unexpected token" error. See old chunks after a deploy.

Checklist

Fix "Page not found" on refresh

  1. 01Confirm the symptom: the app loads from / and links inside it work, but refreshing or opening a deep link such as /dashboard shows Page not found.
  2. 02
    Add the catch-all rewrite as public/_redirects in your project, so the Vite build copies it into dist:
    /*  /index.html  200
  3. 03
    Build locally and confirm dist now holds index.html and a _redirects file:
    npm run build
  4. 04In the Netlify site settings, check that the Build command is npm run build and the Publish directory is dist. Both must match the folder your build creates.
  5. 05Commit, push, wait for the new deploy, then open a deep link in a new tab and refresh it.
  6. 06Add a catch-all route in your router that shows your own not-found page. After the rewrite every unknown path returns index.html, so the router decides what a missing page looks like.

Related

Sources

Official docs behind this checklist

FAQ

FAQ for builders before launch

Why does the page load with npm run dev but not on Netlify?

Vite's appType option defaults to spa, which includes SPA fallback in the dev server and in preview. Netlify serves the published files as they are, so it needs the rewrite rule.

Will the rewrite break my JavaScript files and images?

No. Netlify says you cannot shadow a URL that exists: with /* /index.html 200, a file that exists at the path is still served. Only a status with an exclamation mark, such as 200!, overrides it.

Do I need both a _redirects file and a netlify.toml rule?

No. One catch-all is enough. If both exist, Netlify processes the rules in _redirects first, then the rules in netlify.toml, and uses the first match.