Show recent changelog entries on the homepage
The landing page now previews the latest 3 CHANGELOG.md version sections (rendered Markdown, reusing the same renderer as /changelog), with a link to the full changelog.
4 files changed
+52 −3
M
cmd/gitfed-web/handlers_landing.go
+44 −3
M
cmd/gitfed-web/render.go
+4 −0
M
internal/i18n/strings_en.go
+2 −0
M
internal/i18n/strings_fr.go
+2 −0
cmd/gitfed-web/handlers_landing.go
@@ -4,7 +4,9 @@ import (
"bytes"
"html/template"
"net/http"
+ "strings"
+ "gitfed"
"gitfed/internal/i18n"
)
@@ -68,6 +70,13 @@ var landingTpl = newTpl("landing", `
</div>
</div>
+<div class="changelog-preview">
+ <div class="gf-page-head"><h2>{{t .Lang "landing.changelog_h"}}</h2><a class="see-all" href="/changelog">{{t .Lang "landing.changelog_link"}} {{icon "arrow"}}</a></div>
+ <div class="gf-card">
+ <div class="gf-readme-body markdown-body">{{.ChangelogHTML}}</div>
+ </div>
+</div>
+
<div class="cta-band">
<h2>{{t .Lang "landing.cta_band_h"}}</h2>
<p>{{t .Lang "landing.cta_band_p"}}</p>
@@ -82,14 +91,46 @@ var landingTpl = newTpl("landing", `
</div>
`)
+// recentChangelogEntriesCount caps the landing page's "recent updates"
+// preview — the full history stays one click away at /changelog.
+const recentChangelogEntriesCount = 3
+
+// recentChangelogEntries returns the Markdown source of the first n "## "
+// version sections from CHANGELOG.md (it lists newest first), dropping the
+// leading "# Changelog" title.
+func recentChangelogEntries(n int) string {
+ var out []string
+ sections := 0
+ for _, l := range strings.Split(gitfed.Changelog, "\n") {
+ if strings.HasPrefix(l, "## ") {
+ sections++
+ if sections > n {
+ break
+ }
+ }
+ if sections == 0 {
+ continue
+ }
+ out = append(out, l)
+ }
+ return strings.Join(out, "\n")
+}
+
func (s *server) handleLanding(w http.ResponseWriter, r *http.Request) {
lang := s.lang(r)
_, loggedIn := s.currentSession(r)
+ changelogHTML, err := renderMarkdown(recentChangelogEntries(recentChangelogEntriesCount))
+ if err != nil {
+ s.serverError(w, r, err)
+ return
+ }
+
var buf bytes.Buffer
_ = landingTpl.Execute(&buf, struct {
- Lang string
- LoggedIn bool
- }{string(lang), loggedIn})
+ Lang string
+ LoggedIn bool
+ ChangelogHTML template.HTML
+ }{string(lang), loggedIn, changelogHTML})
s.render(w, r, i18n.T(lang, "landing.title"), "home", template.HTML(buf.String()))
}
cmd/gitfed-web/render.go
@@ -299,6 +299,10 @@ const shellHeadSrc = `<!doctype html>
.fed-diagram { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 1.4rem; }
.fed-diagram svg { width: 100%; height: auto; display: block; }
+ .changelog-preview { margin: 2.8rem 0; }
+ .changelog-preview .gf-page-head { margin-bottom: 1rem; }
+ .changelog-preview .see-all { color: var(--accent); text-decoration: none; font-size: 0.88rem; font-weight: 600; display: inline-flex; align-items: center; gap: 0.35rem; flex-shrink: 0; }
+
.cta-band { text-align: center; padding: 2.4rem 1.4rem; margin: 2.6rem 0 1rem; background: var(--surface); border: 1px solid var(--border); border-radius: 14px; }
.cta-band h2 { font-size: 1.25rem; margin: 0 0 0.5rem; }
.cta-band p { color: var(--text-dim); font-size: 0.9rem; margin: 0 0 1.2rem; }
internal/i18n/strings_en.go
@@ -62,6 +62,8 @@ var en = map[string]string{
"landing.cta_band_h": "Ready to take back control of your code?",
"landing.cta_band_p": "Gitfed is open-source and self-hosted — one Go binary, one embedded database, no external dependencies.",
"landing.cta_band_dashboard": "Go to your repos",
+ "landing.changelog_h": "Recent updates",
+ "landing.changelog_link": "Full changelog",
// ---------- security ----------
"security.title": "Security",
internal/i18n/strings_fr.go
@@ -62,6 +62,8 @@ var fr = map[string]string{
"landing.cta_band_h": "Envie de reprendre la main sur votre code ?",
"landing.cta_band_p": "Gitfed est open-source et auto-hébergé — un binaire Go, une base embarquée, aucune dépendance externe.",
"landing.cta_band_dashboard": "Aller à mes dépôts",
+ "landing.changelog_h": "Dernières mises à jour",
+ "landing.changelog_link": "Changelog complet",
// ---------- security ----------
"security.title": "Sécurité",