Why I Rebuilt My Routing System in Production?
While deploying a Next.js web app to Firebase Hosting, I encountered a frustrating and production-breaking issue:
Refreshing dynamic routes like /page/[id] would consistently throw 404 errors.
This happened despite the app working perfectly in local dev mode. Once hosted on Firebase (with its default static SPA setup), navigating directly to a dynamic route — or refreshing it — failed hard.
Debugging the Issue
Firebase Hosting serves static assets, and unless you’re using Cloud Functions or configuring complex rewrites, it doesn't know how to resolve dynamic paths like /page/123.
Even with attempts at rewrites in firebase.json, I realized the setup was too brittle for a smooth production experience.
My Solution: Switch to Query-Based Routing
Instead of relying on Next.js’s dynamic route folders ([id].tsx), I made a structural change:
diff
Copy
Edit
- /pages/page/[id].tsx
- /pages/page.tsx ➝
/page?id=123
Now all route parameters are passed via query strings, like:- /page?id=123
- /profile?uid=abc
The Results
- No more 404s when refreshing a dynamic route
- Firebase SPA hosting (/index.html) works perfectly
- No need to deploy Cloud Functions or SSR handlers
Faster, more predictable deployments
What Did I Give Up?
Pretty URLs like /page/123 are definitely nicer. But when weighed against:
- Production stability
- Faster iteration
- Fewer moving parts
...the choice was clear for my use case. UX and reliability beat aesthetics.
Key Takeaway
If you’re deploying a static or hybrid Next.js app on Firebase Hosting and running into 404s on refresh:
Query-based routing might be the hidden fix you didn’t know you needed.
Sometimes, a small change in routing can unblock an entire launch.
Let me know if you’ve faced the same issue — and what your workaround was! I’d love to hear how others tackled this.
Top comments (0)