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:
@@ -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)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user