From 9a86b674ff2bbfa597c2b21ccd3e20c6a4243d97 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Mon, 16 Feb 2026 11:28:10 +0100 Subject: [PATCH] bug-fixes --- internal/generator/html.go | 41 +++++++++++++++++++ internal/server/handlers.go | 12 ++++++ static/css/main.css | 79 +++++++++++++++++++++++++++++++++++++ templates/base.html | 13 ++++-- templates/feed.html | 23 +++++++++++ templates/landing.html | 6 +++ 6 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 templates/feed.html diff --git a/internal/generator/html.go b/internal/generator/html.go index 9d2b4fc..f6f27cc 100644 --- a/internal/generator/html.go +++ b/internal/generator/html.go @@ -190,6 +190,7 @@ func NewHTMLGenerator(templateDir string, linkBaseURL, siteName, siteURL, defaul "blog.html", "wiki.html", "contact.html", + "feed.html", "404.html", "500.html", } @@ -793,6 +794,46 @@ func (g *HTMLGenerator) GenerateErrorPage(statusCode int, feedItems []FeedItemIn return g.renderTemplate(fmt.Sprintf("%d.html", statusCode), data) } +// GenerateFeedPage generates a full feed page +func (g *HTMLGenerator) GenerateFeedPage(feedItems []FeedItemInfo) (string, error) { + canonicalURL := g.siteURL + "/feed" + + data := PageData{ + Title: "TheForest Feed", + Description: "Recent notes from TheForest relay", + CanonicalURL: canonicalURL, + OGImage: g.siteURL + g.defaultImage, + OGType: "website", + SiteName: g.siteName, + SiteURL: g.siteURL, + CurrentYear: time.Now().Year(), + WikiPages: []WikiPageInfo{}, + FeedItems: feedItems, + Content: template.HTML(""), // Content comes from template + } + + // Use renderTemplate but with custom data for feed + renderTmpl := template.New("feed-render").Funcs(getTemplateFuncs()) + + files := []string{ + filepath.Join(g.templateDir, "components.html"), + filepath.Join(g.templateDir, "base.html"), + filepath.Join(g.templateDir, "feed.html"), + } + + _, err := renderTmpl.ParseFiles(files...) + if err != nil { + return "", fmt.Errorf("failed to parse feed templates: %w", err) + } + + var buf bytes.Buffer + if err := renderTmpl.ExecuteTemplate(&buf, "base.html", data); err != nil { + return "", fmt.Errorf("failed to execute feed template: %w", err) + } + + return buf.String(), nil +} + // renderTemplate renders a template with the base template func (g *HTMLGenerator) renderTemplate(templateName string, data PageData) (string, error) { // Parse base.html together with the specific template to ensure correct blocks are used diff --git a/internal/server/handlers.go b/internal/server/handlers.go index 0f51f36..00e494b 100644 --- a/internal/server/handlers.go +++ b/internal/server/handlers.go @@ -31,6 +31,7 @@ func (s *Server) setupRoutes(mux *http.ServeMux) { mux.HandleFunc("/articles", s.handleArticles) mux.HandleFunc("/ebooks", s.handleEBooks) mux.HandleFunc("/contact", s.handleContact) + mux.HandleFunc("/feed", s.handleFeed) // Health and metrics mux.HandleFunc("/health", s.handleHealth) @@ -118,6 +119,17 @@ func (s *Server) handleEBooks(w http.ResponseWriter, r *http.Request) { s.servePage(w, r, page) } +// handleFeed handles the Feed page +func (s *Server) handleFeed(w http.ResponseWriter, r *http.Request) { + page, exists := s.cache.Get("/feed") + if !exists { + http.Error(w, "Page not ready", http.StatusServiceUnavailable) + return + } + + s.servePage(w, r, page) +} + // handleContact handles the contact form (GET and POST) func (s *Server) handleContact(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { diff --git a/static/css/main.css b/static/css/main.css index 9662533..a4b902f 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -128,6 +128,20 @@ header { align-items: center; } +.nav-separator { + color: var(--text-secondary); + padding: 0 0.5rem; + user-select: none; +} + +.nav-section-label { + color: var(--text-secondary); + font-weight: 600; + font-size: 0.9em; + padding: 0 0.25rem; + user-select: none; +} + .nav-menu a { color: var(--text-primary); text-decoration: none; @@ -368,6 +382,7 @@ a:focus { .btn:hover { background: var(--link-hover); + color: #1a1a1a; } .btn:active { @@ -383,6 +398,23 @@ a:focus { outline-offset: var(--focus-offset); } +/* Ensure all text and icons inside buttons are black */ +.btn, +.btn *, +.btn span, +.btn .icon-inline, +.btn svg { + color: #1a1a1a !important; +} + +.btn:hover, +.btn:hover *, +.btn:hover span, +.btn:hover .icon-inline, +.btn:hover svg { + color: #1a1a1a !important; +} + /* Landing Page Styles */ .landing-page { max-width: 1200px; @@ -1221,6 +1253,7 @@ textarea:focus-visible { .btn-primary:hover { background: var(--link-hover); + color: #1a1a1a; } .btn-secondary { @@ -1265,6 +1298,52 @@ textarea:focus-visible { } /* E-Books page styles */ +.ebooks-page { + max-width: 1000px; + margin: 0 auto; +} + +.feed-about-blurb { + background: var(--bg-secondary); + padding: 1.5rem; + border-radius: 8px; + border: 1px solid var(--border-color); + margin-bottom: 2rem; +} + +.feed-about-blurb h2 { + color: var(--text-primary); + margin-bottom: 1rem; + font-size: 1.5rem; +} + +.feed-about-blurb p { + margin-bottom: 1rem; + line-height: 1.6; +} + +.feed-about-blurb ul { + margin-left: 1.5rem; + margin-top: 0.5rem; + margin-bottom: 1rem; +} + +.feed-about-blurb li { + margin-bottom: 0.5rem; +} + +.feed-about-blurb code { + background: var(--bg-primary); + padding: 0.2rem 0.4rem; + border-radius: 4px; + font-family: 'Courier New', monospace; + color: var(--accent-color); +} + +.feed-page .feed-container { + margin-top: 2rem; +} + .ebooks-page { max-width: 1200px; margin: 0 auto; diff --git a/templates/base.html b/templates/base.html index bcb3ffd..6d7f669 100644 --- a/templates/base.html +++ b/templates/base.html @@ -48,11 +48,16 @@ diff --git a/templates/feed.html b/templates/feed.html new file mode 100644 index 0000000..1bed205 --- /dev/null +++ b/templates/feed.html @@ -0,0 +1,23 @@ +{{define "content"}} +
+ + +
+

About TheForest Relay

+

TheForest is a Nostr relay operated by GitCitadel. It provides a reliable, fast, and open relay service for the Nostr protocol.

+
    +
  • Relay URL: wss://theforest.nostr1.com
  • +
  • Status: Online and operational
  • +
  • Features: Supports all standard Nostr event kinds
  • +
+

TheForest relay hosts a variety of content, including longform markdown articles (kind 30023), e-books and structured publications (kind 30040), and short-form notes (kind 1).

+
+ +
+ {{template "feed" .}} +
+
+{{end}} diff --git a/templates/landing.html b/templates/landing.html index d4fea55..8427e54 100644 --- a/templates/landing.html +++ b/templates/landing.html @@ -98,6 +98,12 @@ +
+

{{icon "rss"}} Feed

+

Browse recent notes and updates from TheForest relay.

+ {{icon "arrow-right"}} View Feed +
+

{{icon "book"}} E-Books

Discover and download e-books from the decentralized #Alexandria library.