package api import ( "io/fs" "net/http" "strings" ) // StaticHandler serves embedded SPA files with fallback to index.html // for all non-API routes (SPA client-side routing support). func StaticHandler(webFS fs.FS) http.Handler { fileServer := http.FileServer(http.FS(webFS)) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Skip API routes — they are handled by the API router. if strings.HasPrefix(r.URL.Path, "/api") { http.NotFound(w, r) return } // Try to serve the exact file. path := strings.TrimPrefix(r.URL.Path, "/") if path == "" { path = "index.html" } // Check if file exists in the embedded FS. f, err := webFS.Open(path) if err == nil { f.Close() // Clear the JSON content-type set by middleware — let file server decide. w.Header().Del("Content-Type") fileServer.ServeHTTP(w, r) return } // File not found: serve index.html for SPA client-side routing. r.URL.Path = "/" w.Header().Del("Content-Type") fileServer.ServeHTTP(w, r) }) }