feat(related): photo cards — 6 on desktop, 4 on phones, each post's own share card
Deploy / build (push) Successful in 33s
Deploy / build (push) Successful in 33s
Related posts were 4 text-only cards. They now carry the post's language-specific ogImage (/og/<slug>.jpg for EN, /og/zh-<slug>.jpg for ZH), so an English page never shows Chinese art. Grid is 3 across above 900px, 2 across below, and phones show the first 4 only; read-time is dropped under 600px so the date fits. Verified in the built HTML + headless Chrome at 1264/884/500px: 3/2/2 columns, 6/6/4 visible cards, no horizontal overflow, all six images decoded.
This commit is contained in:
1 parent
c8cb2a25f4
commit
7f2680ea92
5 files changed
+61
-15
No files matched your search
@@ -28,7 +28,8 @@ const minutes = readingMinutes(post.body);
|
||||
const fmt = (d: Date) =>
|
||||
d.toLocaleDateString(lang === 'zh' ? 'zh-CN' : 'en-US', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||
|
||||
// Related posts: same language, same category or overlapping tags, excluding self
|
||||
// Related posts: same language, same category or overlapping tags, excluding self.
|
||||
// Six max — the card grid shows all six on desktop and the first four on mobile.
|
||||
const all = await getCollection('posts', ({ data }) => !data.draft);
|
||||
// Tag pills: a tag with its own page becomes a link, a one-off tag stays plain text.
|
||||
const tagCount = tagCounts(all.filter((p) => postLang(p.slug) === lang));
|
||||
@@ -41,7 +42,7 @@ const related = all
|
||||
})
|
||||
.filter((r) => r.score > 0)
|
||||
.sort((a, b) => b.score - a.score)
|
||||
.slice(0, 4)
|
||||
.slice(0, 6)
|
||||
.map((r) => r.post);
|
||||
|
||||
// Translation link for the language switch:
|
||||
@@ -127,15 +128,26 @@ const jsonLd = {
|
||||
<section class="related">
|
||||
<h2>{lang === 'zh' ? '相关文章' : 'Related Posts'}</h2>
|
||||
<div class="related-grid">
|
||||
{related.map((p) => (
|
||||
<a class="related-card" href={`/posts/${p.slug}/`}>
|
||||
{/* Text-only card on purpose: the OG art is illegible at this size
|
||||
(displayed ~526x276) and cost ~46 KB per card. */}
|
||||
{related.map((p, i) => (
|
||||
<a class:list={['related-card', { 'related-extra': i >= 4 }]} href={`/posts/${p.slug}/`}>
|
||||
{/* Each post ships its own language-specific share card (ogImage:
|
||||
/og/<slug>.jpg for EN, /og/zh-<slug>.jpg for ZH), so the related
|
||||
grid never shows the other language's art. */}
|
||||
<img
|
||||
class="related-thumb"
|
||||
src={p.data.ogImage ?? '/og-default.jpg'}
|
||||
alt={p.data.title}
|
||||
width="1200"
|
||||
height="630"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
<div class="related-body">
|
||||
<span class="related-badge">{p.data.category}</span>
|
||||
<h3>{p.data.title}</h3>
|
||||
<time datetime={p.data.pubDate.toISOString()}>
|
||||
{fmt(p.data.pubDate)} · {readingMinutes(p.body)} {lang === 'zh' ? '分钟' : 'min read'}
|
||||
{fmt(p.data.pubDate)}
|
||||
<span class="related-read"> · {readingMinutes(p.body)} {lang === 'zh' ? '分钟' : 'min read'}</span>
|
||||
</time>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
Reference in new issue
Block a user