Skip to content

Commit 77c4446

Browse files
committed
if <3 related posts, add more based on tags and recency
1 parent 6db044f commit 77c4446

2 files changed

Lines changed: 52 additions & 2 deletions

File tree

src/components/organisms/Navigation.astro

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,12 @@ const isActive = (href: string) => {
7171
<!-- Right side: Actions + Mobile Menu -->
7272
<div class="flex items-center gap-4">
7373
<!-- Search Button -->
74-
<Button variant="outline" type="button" id="search-button">
74+
<Button
75+
variant="outline"
76+
type="button"
77+
id="search-button"
78+
class="cursor-pointer"
79+
>
7580
<MagnifyingGlassIcon />
7681
</Button>
7782

src/pages/blog/[slug].astro

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ const authors = post.data.authors
3434
3535
// Get related posts
3636
const allPosts = await getCollection('blog');
37-
const relatedPosts = post.data.relatedPosts
37+
38+
// First, get manually selected related posts
39+
let relatedPosts = post.data.relatedPosts
3840
? post.data.relatedPosts
3941
.filter(permalink => permalink !== post.data.permalink) // Don't show current post
4042
.map((permalink) => {
@@ -59,6 +61,49 @@ const relatedPosts = post.data.relatedPosts
5961
.filter((post): post is NonNullable<typeof post> => post !== null)
6062
: [];
6163
64+
// If we have less than 3 related posts, dynamically add more based on tag matching and recency
65+
if (relatedPosts.length < 3) {
66+
const currentTags = new Set(post.data.tags);
67+
const manuallySelectedPermalinks = new Set(relatedPosts.map(p => p.data.permalink));
68+
69+
// Calculate tag matches for all other posts
70+
const candidatePosts = allPosts
71+
.filter(p =>
72+
p.data.permalink !== post.data.permalink && // Not the current post
73+
!manuallySelectedPermalinks.has(p.data.permalink) && // Not already manually selected
74+
(isDev || p.data.published === 'published') // Only published posts (except in dev)
75+
)
76+
.map(p => {
77+
// Count matching tags
78+
const matchingTags = p.data.tags.filter(tag => currentTags.has(tag)).length;
79+
80+
// Resolve authors
81+
const resolvedAuthors = p.data.authors
82+
.map((id) => peopleMap.get(id))
83+
.filter(Boolean);
84+
85+
return {
86+
...p,
87+
resolvedAuthors,
88+
matchingTags
89+
};
90+
})
91+
.sort((a, b) => {
92+
// First sort by number of matching tags (descending)
93+
if (b.matchingTags !== a.matchingTags) {
94+
return b.matchingTags - a.matchingTags;
95+
}
96+
// Then sort by publish date (most recent first)
97+
return b.data.publishedDate.getTime() - a.data.publishedDate.getTime();
98+
});
99+
100+
// Add posts to fill up to 3 total
101+
const postsNeeded = 3 - relatedPosts.length;
102+
const dynamicPosts = candidatePosts.slice(0, postsNeeded);
103+
104+
relatedPosts = [...relatedPosts, ...dynamicPosts];
105+
}
106+
62107
// Format date
63108
const formatDate = (date: Date) => {
64109
return new Intl.DateTimeFormat('en-US', {

0 commit comments

Comments
 (0)