feat(ui): add wedding theme styles and layout components

* Introduced wedding-themed CSS variables for styling.
* Created layout component for the wedding site with navigation and countdown.
* Added RSVP and photo upload pages with form handling.
* Implemented QR code page for wedding site access.
* Configured TypeScript and Vite for the project.
* Added robots.txt for search engine crawling.
This commit is contained in:
2026-08-11 23:31:35 +02:00
commit 39f5b8d5cc
89 changed files with 6829 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
package main
import (
"embed"
"fmt"
"io/fs"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"wedding-server/internal/api"
"wedding-server/internal/config"
"wedding-server/internal/mail"
"wedding-server/internal/store"
)
//go:embed web/dist
var embeddedWeb embed.FS
func main() {
cfgPath := config.Path()
cfg, err := config.Load(cfgPath)
if err != nil {
log.Fatalf("config: %v", err)
}
if err := os.MkdirAll(cfg.Storage.DataDir, 0o755); err != nil {
log.Fatalf("data dir: %v", err)
}
st, err := store.Open(cfg.Storage.DataDir)
if err != nil {
log.Fatalf("store: %v", err)
}
defer st.Close()
mailer := mail.New(cfg.Email)
mux := http.NewServeMux()
api.New(cfg, st, mailer).Routes(mux)
uploadsDir := filepath.Join(cfg.Storage.DataDir, "photos")
mux.Handle("/uploads/", http.StripPrefix("/uploads/", http.FileServer(http.Dir(uploadsDir))))
webFS, err := fs.Sub(embeddedWeb, "web/dist")
if err != nil {
log.Fatalf("embedded web assets: %v", err)
}
mux.Handle("/", staticHandler(webFS))
addr := fmt.Sprintf(":%d", cfg.Server.Port)
log.Printf("listening on %s", addr)
if err := http.ListenAndServe(addr, mux); err != nil {
log.Fatal(err)
}
}
// staticHandler serves the prerendered SvelteKit build, where routes are
// written as flat files (e.g. "rsvp.html") rather than "rsvp/index.html".
func staticHandler(fsys fs.FS) http.Handler {
fileServer := http.FileServer(http.FS(fsys))
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
p := strings.TrimPrefix(r.URL.Path, "/")
if p == "" {
p = "index.html"
}
if _, err := fs.Stat(fsys, p); err != nil {
if _, err := fs.Stat(fsys, p+".html"); err == nil {
r2 := *r
r2.URL.Path = "/" + p + ".html"
fileServer.ServeHTTP(w, &r2)
return
}
}
fileServer.ServeHTTP(w, r)
})
}