From c78a35377a586635f55f319e4b2c081e03acf13e Mon Sep 17 00:00:00 2001 From: James Griffin Date: Wed, 8 Apr 2026 19:10:07 -0300 Subject: [PATCH] Fix SPA routing: serve index.html for non-file paths Replace bare http.FileServer with an SPA-aware handler that tries to serve the requested static file and falls back to index.html when the path doesn't match a real file. This lets React Router handle client-side routes like /schedules on page reload. Co-Authored-By: Claude Opus 4.6 --- internal/server/server.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/internal/server/server.go b/internal/server/server.go index 6a9f3ae..a1f6d01 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -94,8 +94,25 @@ func New(db *sql.DB, jwtSecret string, staticDir string) http.Handler { }) }) - // Serve static React app for all other routes - r.Handle("/*", http.FileServer(http.Dir(staticDir))) + // Serve static React app for all other routes, with SPA fallback + r.Handle("/*", spaHandler(staticDir)) return r } + +// spaHandler serves static files from dir, falling back to index.html for +// paths that don't match a file on disk (so client-side routing works). +func spaHandler(dir string) http.HandlerFunc { + fs := http.Dir(dir) + fileServer := http.FileServer(fs) + return func(w http.ResponseWriter, r *http.Request) { + // Try to open the requested path as a static file. + if f, err := fs.Open(r.URL.Path); err == nil { + f.Close() + fileServer.ServeHTTP(w, r) + return + } + // Not a real file — serve index.html and let React Router handle it. + http.ServeFile(w, r, dir+"/index.html") + } +}