A community based topic aggregation platform built on atproto
at main 58 lines 1.8 kB view raw
1// Package web provides HTTP handlers and templates for the Coves web interface. 2// This includes the landing page and static file serving for the coves.social website. 3package web 4 5import ( 6 "embed" 7 "fmt" 8 "html/template" 9 "net/http" 10 "path/filepath" 11) 12 13//go:embed templates/*.html 14var templatesFS embed.FS 15 16// Templates holds the parsed HTML templates for the web interface. 17type Templates struct { 18 templates *template.Template 19} 20 21// NewTemplates creates a new Templates instance by parsing all embedded templates. 22func NewTemplates() (*Templates, error) { 23 tmpl, err := template.ParseFS(templatesFS, "templates/*.html") 24 if err != nil { 25 return nil, fmt.Errorf("failed to parse templates: %w", err) 26 } 27 return &Templates{templates: tmpl}, nil 28} 29 30// Render renders a named template with the provided data to the response writer. 31// Returns an error if the template doesn't exist or rendering fails. 32func (t *Templates) Render(w http.ResponseWriter, name string, data interface{}) error { 33 // Set content type before writing 34 w.Header().Set("Content-Type", "text/html; charset=utf-8") 35 36 // Check if template exists 37 tmpl := t.templates.Lookup(name) 38 if tmpl == nil { 39 return fmt.Errorf("template %q not found", name) 40 } 41 42 // Execute template 43 if err := tmpl.Execute(w, data); err != nil { 44 return fmt.Errorf("failed to execute template %q: %w", name, err) 45 } 46 47 return nil 48} 49 50// ProjectStaticFileServer returns an http.Handler that serves static files from the project root. 51// This is used for files that live outside the web package (e.g., /static/images/). 52func ProjectStaticFileServer(staticDir string) http.Handler { 53 absPath, err := filepath.Abs(staticDir) 54 if err != nil { 55 panic(fmt.Sprintf("failed to get absolute path for static directory: %v", err)) 56 } 57 return http.StripPrefix("/static/", http.FileServer(http.Dir(absPath))) 58}