package main import ( "io/fs" "log" "net/http" "krafttrainer/internal/handler" mig "krafttrainer/internal/migrate" "krafttrainer/internal/store" "krafttrainer/migrations" "krafttrainer/static" ) func main() { // Datenbank initialisieren s, err := store.New("krafttrainer.db") if err != nil { log.Fatalf("Datenbank: %v", err) } defer s.Close() // Migrationen ausführen if err := mig.Run(s.DB(), migrations.FS); err != nil { log.Fatalf("Migrationen: %v", err) } log.Println("Migrationen erfolgreich") // HTTP-Routen mux := http.NewServeMux() h := handler.New(s) h.RegisterRoutes(mux) // SPA-Fallback: statische Dateien aus embed.FS servieren mux.Handle("/", spaHandler(static.FS)) // Middleware-Chain und Server starten srv := handler.Chain(mux, handler.Recoverer, handler.RequestLogger, handler.CORS) log.Println("Server startet auf :8090") if err := http.ListenAndServe(":8090", srv); err != nil { log.Fatalf("Server: %v", err) } } // spaHandler serviert statische Dateien und fällt auf index.html zurück (SPA-Routing). func spaHandler(embeddedFS fs.FS) http.Handler { fileServer := http.FileServer(http.FS(embeddedFS)) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { path := r.URL.Path if path == "/" { path = "index.html" } else if len(path) > 0 && path[0] == '/' { path = path[1:] } f, err := embeddedFS.Open(path) if err != nil { // SPA-Fallback: index.html für unbekannte Pfade r.URL.Path = "/" } else { f.Close() } fileServer.ServeHTTP(w, r) }) }