From 9db2500fb340ef304c0f15f4379bc33589df9a63 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Thu, 12 Feb 2026 21:44:23 -0800 Subject: Scaffold new frontend and close NK-t0nmbj --- web/frontend.go | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 web/frontend.go (limited to 'web/frontend.go') diff --git a/web/frontend.go b/web/frontend.go new file mode 100644 index 0000000..c3ee038 --- /dev/null +++ b/web/frontend.go @@ -0,0 +1,55 @@ +package web + +import ( + "net/http" + "path/filepath" + "strings" + + rice "github.com/GeertJohan/go.rice" +) + +func ServeFrontend(w http.ResponseWriter, r *http.Request) { + // The box is at "web", so we look for "../frontend/dist" relative to it + // rice will find this box by the string literal + box := rice.MustFindBox("../frontend/dist") + + // Get the file path from the URL + path := r.URL.Path + // rice box paths shouldn't start with / + path = strings.TrimPrefix(path, "/") + + // If path is empty, it's index.html + if path == "" { + path = "index.html" + } + + // Try to open the file + f, err := box.Open(path) + if err != nil { + // If file not found, serve index.html for client-side routing + // But only if it's not looking for a specific static asset (like .js, .css) + // Simple heuristic: if it has an extension, it's probably an asset + if !strings.Contains(filepath.Base(path), ".") { + f, err = box.Open("index.html") + if err != nil { + http.Error(w, "frontend not found", http.StatusNotFound) + return + } + // Important: update path so ServeContent sets correct Content-Type + path = "index.html" + } else { + // It might be a real 404 for an asset + http.Error(w, "not found", http.StatusNotFound) + return + } + } + defer f.Close() + + d, err := f.Stat() + if err != nil { + http.Error(w, "internal error", http.StatusInternalServerError) + return + } + + http.ServeContent(w, r, path, d.ModTime(), f) +} -- cgit v1.2.3