Monorepo for Tangled tangled.org
2

Configure Feed

Select the types of activity you want to include in your feed.

appview/timeline: process recent blog posts and show on timeline

Signed-off-by: oppiliappan <me@oppi.li>

author
oppiliappan
committer
Tangled
date (Jun 8, 2026, 5:59 PM +0300) commit 62d59cb8 parent ba8bc136 change-id ptozllop
+78 -31
+8
appview/pages/pages.go
··· 407 407 Pull *models.Pull 408 408 } 409 409 410 + type BlogPost struct { 411 + Slug string 412 + Title string 413 + Subtitle string 414 + Date time.Time 415 + } 416 + 410 417 type TimelineParams struct { 411 418 LoggedInUser *oauth.MultiAccountUser 412 419 Timeline []models.TimelineGroup ··· 417 424 Notifications []*models.NotificationWithEntity 418 425 Recents []RecentItem 419 426 FollowingOnly bool 427 + RecentBlogPosts []BlogPost 420 428 // ShowNewsletter controls whether the newsletter widget/CTA is rendered. 421 429 // For logged-in users it reflects their newsletter_preferences row; for 422 430 // anonymous visitors it is always true (dismissal falls back to
+38 -23
appview/pages/templates/timeline/fragments/announcements.html
··· 4 4 {{ i "megaphone" "size-4 flex-shrink-0" }} 5 5 Announcements 6 6 </h3> 7 - <div class="flex flex-col gap-3 p-2 bg-white dark:bg-gray-800"> 7 + <div class="flex flex-col p-0 bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700"> 8 8 {{ template "vouchAnnouncement" . }} 9 + {{ if .RecentBlogPosts }} 10 + {{ template "recentBlogPosts" . }} 11 + {{ end }} 9 12 </div> 10 13 </div> 11 14 {{ end }} 12 15 16 + {{ define "recentBlogPosts" }} 17 + <div class="flex flex-col hidden md:block"> 18 + {{ range .RecentBlogPosts }} 19 + <a href="https://blog.tangled.org/{{ .Slug }}" class="text-sm no-underline hover:no-underline hover:bg-gray-100/50 dark:hover:bg-gray-700/50 overflow-hidden p-4 flex flex-col gap-0.5"> 20 + <span class="truncate text-xs text-gray-500 dark:text-gray-400">{{ .Date.Format "January 2, 2006" }}</span> 21 + <span class="truncate dark:text-white">{{ .Title }}</span> 22 + {{ if .Subtitle }}<span class="line-clamp-1 text-sm text-gray-500 dark:text-gray-400">{{ .Subtitle }}</span>{{ end }} 23 + </a> 24 + {{ end }} 25 + </div> 26 + {{ end }} 27 + 13 28 {{ define "vouchAnnouncement" }} 14 - <div class="relative overflow-hidden border border-indigo-200 dark:border-indigo-700 bg-gradient-to-b from-white to-indigo-50 dark:from-indigo-950 dark:to-indigo-900 rounded-sm p-6"> 15 - <div class="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_at_bottom_left,rgba(165,180,252,0.35),transparent_70%)] dark:bg-[radial-gradient(ellipse_at_bottom_left,rgba(99,102,241,0.2),transparent_70%)]"></div> 16 - <div class="relative z-10"> 17 - <p class="font-semibold text-indigo-800 dark:text-indigo-300 mb-1">Build a web of trust</p> 18 - <p class="text-indigo-700 dark:text-indigo-400"> 19 - Vouch for trustworthy users that make open-source a better place. Visit a user's 20 - profile to vouch for them. 21 - </p> 29 + <div class="relative overflow-hidden bg-gradient-to-b from-white to-indigo-50 dark:from-indigo-950 dark:to-indigo-900 rounded-sm p-4"> 30 + <div class="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_at_bottom_left,rgba(165,180,252,0.35),transparent_70%)] dark:bg-[radial-gradient(ellipse_at_bottom_left,rgba(99,102,241,0.2),transparent_70%)]"></div> 31 + <div class="relative z-10"> 32 + <p class="font-semibold text-indigo-800 dark:text-indigo-300 mb-1">Build a web of trust</p> 33 + <p class="text-indigo-700 dark:text-indigo-400"> 34 + Vouch for trustworthy users that make open-source a better place. Visit a user's 35 + profile to vouch for them. 36 + </p> 22 37 23 - <div class="mt-3 flex items-center justify-between"> 24 - <a class="mt-3 no-underline inline-flex items-center gap-1 text-sm font-medium text-indigo-700 dark:text-indigo-300 hover:text-indigo-900 dark:hover:text-indigo-100 hover:underline" href="https://blog.tangled.org/vouching"> 25 - Read more 26 - </a> 27 - {{ if and .LoggedInUser .VouchSuggestions }} 28 - <a class="md:hidden mt-3 no-underline inline-flex items-center gap-1 text-sm font-medium text-indigo-700 dark:text-indigo-300 hover:text-indigo-900 dark:hover:text-indigo-100 hover:underline" href="/{{ .LoggedInUser.Did }}?tab=vouches"> 29 - View suggestions {{ i "arrow-right" "size-3.5" }} 30 - </a> 31 - {{ end }} 32 - </div> 33 - 38 + <div class="mt-3 flex items-center justify-between"> 39 + <a class="mt-3 no-underline inline-flex items-center gap-1 text-sm font-medium text-indigo-700 dark:text-indigo-300 hover:text-indigo-900 dark:hover:text-indigo-100 hover:underline" href="https://blog.tangled.org/vouching"> 40 + Read more 41 + </a> 42 + {{ if and .LoggedInUser .VouchSuggestions }} 43 + <a class="md:hidden mt-3 no-underline inline-flex items-center gap-1 text-sm font-medium text-indigo-700 dark:text-indigo-300 hover:text-indigo-900 dark:hover:text-indigo-100 hover:underline" href="/{{ .LoggedInUser.Did }}?tab=vouches"> 44 + View suggestions {{ i "arrow-right" "size-3.5" }} 45 + </a> 46 + {{ end }} 34 47 </div> 35 48 36 - <div class="pointer-events-none absolute -bottom-8 -right-16 text-indigo-200 dark:text-indigo-700 opacity-60"> 37 - {{ i "shield-plus" "size-48" }} 38 - </div> 49 + </div> 50 + 51 + <div class="pointer-events-none absolute -bottom-8 -right-16 text-indigo-200 dark:text-indigo-700 opacity-60"> 52 + {{ i "shield-plus" "size-48" }} 39 53 </div> 54 + </div> 40 55 {{ end }}
+19
appview/pages/templates/timeline/fragments/timeline.html
··· 35 35 {{ end }} 36 36 </div> 37 37 38 + {{ if .Timeline }} 38 39 <div class="flex flex-col gap-4"> 39 40 {{ range $i, $g := .Timeline }} 40 41 <div class="relative"> ··· 54 55 </div> 55 56 {{ end }} 56 57 </div> 58 + {{ else }} 59 + <div class="px-4 py-8 text-sm text-center text-gray-400 dark:text-gray-500 border border-gray-200 dark:border-gray-700 rounded-sm "> 60 + <div class="w-10 h-10 mx-auto mb-3 text-gray-300 dark:text-gray-600"> 61 + {{ if .FollowingOnly }} 62 + {{ i "user-round-x" "size-10" }} 63 + {{ else }} 64 + {{ i "radio" "size-10" }} 65 + {{ end }} 66 + </div> 67 + <p class="text-sm text-gray-500 dark:text-gray-400"> 68 + {{ if .FollowingOnly }} 69 + Follow some users to see their activity here. 70 + {{ else }} 71 + Nothing here yet. 72 + {{ end }} 73 + </p> 74 + </div> 75 + {{ end }} 57 76 </div> 58 77 {{ end }} 59 78
+5 -3
appview/pages/templates/timeline/timeline.html
··· 32 32 </div> 33 33 {{ end }} 34 34 35 - {{ template "timeline/fragments/announcements" . }} 35 + {{ template "timeline/fragments/trending" . }} 36 + 37 + <div class="hidden md:block"> 38 + {{ template "timeline/fragments/announcements" . }} 39 + </div> 36 40 37 41 {{ if and .LoggedInUser .VouchSuggestions }} 38 42 <div class="hidden md:block"> 39 43 {{ template "timeline/fragments/vouchSuggestions" . }} 40 44 </div> 41 45 {{ end }} 42 - 43 - {{ template "timeline/fragments/trending" . }} 44 46 </div> 45 47 </div> 46 48
+8 -5
appview/timeline/router.go
··· 7 7 "net/http" 8 8 "os" 9 9 "strings" 10 + "time" 10 11 11 12 "github.com/adrg/frontmatter" 12 13 "github.com/go-chi/chi/v5" ··· 17 18 ) 18 19 19 20 type postMeta struct { 20 - Slug string `yaml:"slug"` 21 - Title string `yaml:"title"` 22 - Date string `yaml:"date"` 23 - Draft bool `yaml:"draft"` 21 + Slug string `yaml:"slug"` 22 + Title string `yaml:"title"` 23 + Subtitle string `yaml:"subtitle"` 24 + Date string `yaml:"date"` 25 + Draft bool `yaml:"draft"` 24 26 } 25 27 26 28 type Timeline struct { ··· 99 101 100 102 result := make([]pages.BlogPost, len(posts)) 101 103 for i, p := range posts { 102 - result[i] = pages.BlogPost{Slug: p.Slug, Title: p.Title, Date: p.Date} 104 + t, _ := time.Parse("2006-01-02", p.Date) 105 + result[i] = pages.BlogPost{Slug: p.Slug, Title: p.Title, Subtitle: p.Subtitle, Date: t} 103 106 } 104 107 return result 105 108 }