LabCodeHub öffentliche Ansicht
Anmelden
Küpper / Quildrop öffentlich

feat: add navigation for previous and next posts

R Rüdiger Küpper <rpr@9it.de> committete am 19.02.2026 02:21
d1bf374fa130243a8a3a18ff4545bbdd270e9448
5 geänderte Datei(en) +110 −6
Kontextzeilen: 0 1 2 3 10
geändert internal/generator/generator.go
+10 −2 Datei ansehen
@@ -70 +70 @@ func Generate(cfg *config.Config, posts []*content.Post, pages []*content.Page)
70 -
	for _, post := range posts {
70 +
	for i, post := range posts {
@@ -72,0 +73,8 @@ func Generate(cfg *config.Config, posts []*content.Post, pages []*content.Page)
73 +
		data := templates.PostData{Site: site, Post: post}
74 +
		// Posts are sorted newest first: index 0 = newest
75 +
		if i > 0 {
76 +
			data.PrevPost = posts[i-1] // newer
77 +
		}
78 +
		if i < len(posts)-1 {
79 +
			data.NextPost = posts[i+1] // older
80 +
		}
@@ -74 +82 @@ func Generate(cfg *config.Config, posts []*content.Post, pages []*content.Page)
74 -
			return templates.RenderPost(f, templates.PostData{Site: site, Post: post})
82 +
			return templates.RenderPost(f, data)
geändert internal/server/server.go
+11 −1 Datei ansehen
@@ -24 +24,2 @@ func Start(cfg *config.Config, posts []*content.Post, pages []*content.Page) {
24 -
	for _, p := range posts {
24 +
	postIndex := make(map[string]int)
25 +
	for i, p := range posts {
@@ -25,0 +27 @@ func Start(cfg *config.Config, posts []*content.Post, pages []*content.Page) {
27 +
		postIndex[p.Slug] = i
@@ -176,0 +179,8 @@ func Start(cfg *config.Config, posts []*content.Post, pages []*content.Page) {
179 +
		// Posts are sorted newest first: index 0 = newest
180 +
		idx := postIndex[slug]
181 +
		if idx > 0 {
182 +
			data.PrevPost = posts[idx-1] // newer
183 +
		}
184 +
		if idx < len(posts)-1 {
185 +
			data.NextPost = posts[idx+1] // older
186 +
		}
geändert internal/templates/post.html
+18 −0 Datei ansehen
@@ -26,0 +27,18 @@
27 +
    <nav class="post-nav">
28 +
        {{if .PrevPost}}
29 +
        <a href="/posts/{{.PrevPost.Slug}}/" class="post-nav-link post-nav-prev">
30 +
            <span class="post-nav-label">&larr; Neuerer Artikel</span>
31 +
            <span class="post-nav-title">{{.PrevPost.Title}}</span>
32 +
        </a>
33 +
        {{else}}
34 +
        <span class="post-nav-link post-nav-prev disabled"></span>
35 +
        {{end}}
36 +
        {{if .NextPost}}
37 +
        <a href="/posts/{{.NextPost.Slug}}/" class="post-nav-link post-nav-next">
38 +
            <span class="post-nav-label">Älterer Artikel &rarr;</span>
39 +
            <span class="post-nav-title">{{.NextPost.Title}}</span>
40 +
        </a>
41 +
        {{else}}
42 +
        <span class="post-nav-link post-nav-next disabled"></span>
43 +
        {{end}}
44 +
    </nav>
geändert internal/templates/render.go
+4 −2 Datei ansehen
@@ -34,2 +34,4 @@ type PostData struct {
34 -
	Site SiteData
35 -
	Post *content.Post
34 +
	Site     SiteData
35 +
	Post     *content.Post
36 +
	PrevPost *content.Post // newer post (nil if this is the newest)
37 +
	NextPost *content.Post // older post (nil if this is the oldest)
geändert static/css/style.css
+67 −1 Datei ansehen
@@ -904 +904,4 @@ body {
904 -
.post-footer {
904 +
/* === Post Navigation (Prev/Next) === */
905 +
.post-nav {
906 +
    display: flex;
907 +
    gap: 1.5rem;
@@ -909,0 +913,63 @@ body {
913 +
.post-nav-link {
914 +
    flex: 1;
915 +
    display: flex;
916 +
    flex-direction: column;
917 +
    gap: 0.3rem;
918 +
    padding: 1rem;
919 +
    border-radius: 10px;
920 +
    background: var(--bg-card);
921 +
    border: 1px solid var(--border);
922 +
    text-decoration: none;
923 +
    transition: all 0.2s ease;
924 +
}
925 +
926 +
.post-nav-link:hover {
927 +
    border-color: var(--accent);
928 +
    background: var(--bg-card-hover);
929 +
    box-shadow: 0 0 16px var(--accent-glow);
930 +
}
931 +
932 +
.post-nav-link.disabled {
933 +
    visibility: hidden;
934 +
}
935 +
936 +
.post-nav-prev {
937 +
    align-items: flex-start;
938 +
}
939 +
940 +
.post-nav-next {
941 +
    align-items: flex-end;
942 +
    text-align: right;
943 +
}
944 +
945 +
.post-nav-label {
946 +
    font-family: 'JetBrains Mono', monospace;
947 +
    font-size: 0.75rem;
948 +
    color: var(--text-muted);
949 +
    text-transform: uppercase;
950 +
    letter-spacing: 0.05em;
951 +
}
952 +
953 +
.post-nav-title {
954 +
    font-size: 0.9rem;
955 +
    font-weight: 600;
956 +
    color: var(--accent);
957 +
    line-height: 1.3;
958 +
}
959 +
960 +
@media (max-width: 640px) {
961 +
    .post-nav {
962 +
        flex-direction: column;
963 +
        gap: 0.75rem;
964 +
    }
965 +
    .post-nav-next {
966 +
        align-items: flex-start;
967 +
        text-align: left;
968 +
    }
969 +
}
970 +
971 +
.post-footer {
972 +
    margin-top: 1.5rem;
973 +
    padding-top: 1rem;
974 +
}
975 +