🚀 The One-Line Fix That Instantly Solves Page Refresh 404 Errors on Vercel (Vite + React + Supabase)
If you’ve ever deployed a Vite + React application to Vercel and felt confident — only to be hit with a 404 NOT_FOUND error the moment you refresh a page, you’re not alone. This issue affects dashboards, admin panels, RAG agents, and almost every Single Page Application (SPA) built with client-side routing.
The good news?
The fix is simple, reliable, and production-safe.
The Problem: Why Refreshing Breaks Your App
In Vite + React apps, routing is handled entirely in the browser using tools like React Router’s BrowserRouter. Routes such as /dashboard, /attendance, or /chat don’t exist as real files on the server.
When you click links inside the app, everything works because React handles navigation.
But when you refresh the page, Vercel does the following:
- Receives a request for
/attendance - Looks for
/attendance.html - Doesn’t find it
- Returns 404 NOT_FOUND
This has nothing to do with Supabase authentication, session expiry, or broken code. It’s purely how static hosting works with SPAs.
💡 The Solution: A Single Rewrite Rule That Fixes Everything
The correct solution is to tell Vercel:
“For any route, always serve
index.htmland let React handle routing.”
You do this by adding a vercel.json file at the root of your project.
✅ vercel.json
{
"rewrites": [
{
"source": "/(.*)",
"destination": "/index.html"
}
]
}That’s it.
After committing and redeploying:
- Page refreshes work
- Deep links work
- All routes load correctly
- No more 404 errors
This solution applies to any Vite + React SPA deployed on Vercel, including dashboards, RAG agents, admin panels, and internal tools.
What About Supabase Sessions? Are Users Still Logged In?
Yes — Supabase sessions persist across refreshes.
Get Bonface Alfonce’s stories in your inbox
Join Medium for free to get updates from this writer.
Supabase stores authentication data securely in browser storage and automatically restores the session when the app reloads. Once the routing issue is fixed, your app can load normally and Supabase can rehydrate the user session without interruption.
However, to ensure sessions last longer and remain engaged, here are some best practices.
🔐 Tips to Keep Supabase Sessions Alive & Users Engaged
1. Increase Session Duration
In your Supabase dashboard:
- Go to Authentication → Settings
- Increase JWT expiry if appropriate for your app
- Enable refresh token rotation
This allows silent session renewal without forcing re-login.
2. Restore Session on App Load
Always check and restore the session when your app initializes:
- Use
onAuthStateChange - Or fetch the session once inside your Auth context/provider
This ensures the UI stays in sync after refresh.
3. Avoid Logging Out on Temporary Errors
Network hiccups or delayed API responses should not force logout. Handle errors gracefully and retry before invalidating a session.
4. Use Activity to Keep Users Engaged
- Periodically refresh data with tools like React Query
- Show real-time indicators (last sync, online status)
- Keep the app “alive” so users don’t feel disconnected
Final thoughts
This issue frustrates many developers because it feels like an authentication or framework bug — but it isn’t. It’s simply a missing deployment configuration.
By adding one small rewrite rule, you unlock:
- Reliable refresh behavior
- Stable Supabase sessions
- Production-ready SPA deployments on Vercel
If you’re building modern web apps with Vite, React, and Supabase, this fix should be part of your default deployment checklist.










