Add svelte-heros icon library

- Install svelte-heros for consistent Heroicons usage
- Replace inline SVGs for password toggle with Eye/EyeOff icons
- Fix USE_EMBEDDED mode to serve frontend from filesystem
This commit is contained in:
Christoph Haas 2026-03-29 15:16:58 +02:00
parent 8b2d2649ac
commit 46d9ff26dd
5 changed files with 49 additions and 45 deletions

View file

@ -4,15 +4,22 @@ import (
"embed"
"io/fs"
"net/http"
"os"
)
//go:embed all:embed
var Files embed.FS
func FrontendFileSystem() http.FileSystem {
return http.FS(Files)
func FrontendFileSystem() (http.FileSystem, string) {
if os.Getenv("USE_EMBEDDED") == "false" {
return http.Dir("../frontend/build"), ""
}
return http.FS(Files), "embed/"
}
func FrontendFS() fs.FS {
if os.Getenv("USE_EMBEDDED") == "false" {
return os.DirFS("../frontend/build")
}
return Files
}

View file

@ -120,7 +120,7 @@ func main() {
// Get the embedded filesystem containing the frontend.
// The frontend is compiled into the binary during build time.
frontendFS := FrontendFileSystem()
frontendFS, frontendPrefix := FrontendFileSystem()
// Set Gin mode based on environment.
// USE_EMBEDDED=false means development mode (e.g., via air hot-reloader).
@ -142,31 +142,31 @@ func main() {
// Set up SPA fallback for non-API routes.
// This must be the last route to catch all unmatched paths.
engine.NoRoute(func(c *gin.Context) {
path := c.Request.URL.Path
reqPath := c.Request.URL.Path
// If it's an API path, return 404.
// The API router should have handled /api/* routes.
if strings.HasPrefix(path, "/api/") {
if strings.HasPrefix(reqPath, "/api/") {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
// Serve SvelteKit hashed assets at /_app/*
if strings.HasPrefix(path, "/_app/") {
assetPath := "embed/_app/" + strings.TrimPrefix(path, "/_app/")
serveGinStaticFile(c, frontendFS, assetPath)
if strings.HasPrefix(reqPath, "/_app/") {
filePath := frontendPrefix + "_app/" + strings.TrimPrefix(reqPath, "/_app/")
serveGinStaticFile(c, frontendFS, filePath)
return
}
// Serve favicon
if path == "/favicon.png" {
serveGinStaticFile(c, frontendFS, "embed/favicon.png")
if reqPath == "/favicon.png" {
serveGinStaticFile(c, frontendFS, frontendPrefix+"favicon.png")
return
}
// For all other paths, serve the SPA index.html.
// This allows client-side routing (e.g., /domains/example.org).
serveGinStaticFile(c, frontendFS, "embed/index.html")
serveGinStaticFile(c, frontendFS, frontendPrefix+"index.html")
})
// Build the address string for binding: "IP:PORT"