schmelczer-dev/src/pages/articles/index.astro
2026-05-26 08:28:37 +01:00

75 lines
2.1 KiB
Text

---
import ArticleList from '../../components/ArticleList.astro';
import TagList from '../../components/TagList.astro';
import Page from '../../layouts/Page.astro';
import {
absoluteUrl,
articlePath,
buildBreadcrumbJsonLd,
buildBreadcrumbTrail,
getAllTags,
getPublishedPosts,
optimizeOgImage,
site,
yearOf,
} from '../../lib/site';
const description =
'Technical articles and notes about projects, systems, AI deployment, graphics, simulations, and tools.';
const posts = await getPublishedPosts();
const years = [...new Set(posts.map((post) => yearOf(post.data.date)))];
const tags = getAllTags(posts);
const postOgImages = await Promise.all(
posts.map((post) => optimizeOgImage(post.data.thumbnail.src))
);
const personId = absoluteUrl('/about/#person');
const blogJsonLd = {
'@context': 'https://schema.org',
'@type': 'Blog',
name: `${site.name}: Articles`,
url: absoluteUrl('/articles/'),
description,
publisher: { '@id': personId },
blogPost: posts.map((post, index) => ({
'@type': 'BlogPosting',
headline: post.data.title,
description: post.data.description,
datePublished: post.data.date.toISOString(),
url: absoluteUrl(articlePath(post)),
author: { '@id': personId },
image: absoluteUrl(postOgImages[index].src),
keywords: post.data.tags.join(', '),
})),
};
const breadcrumbJsonLd = buildBreadcrumbJsonLd(buildBreadcrumbTrail({ articles: true }));
const jsonLd = [blogJsonLd, breadcrumbJsonLd];
---
<Page title="Articles" description={description} jsonLd={jsonLd}>
<nav id="tag-filter" class="tag-filter" aria-label="Browse by tag">
<span>Browse by tag</span>
<TagList tags={tags} />
</nav>
{
years.map((year) => {
const postsForYear = posts.filter((post) => yearOf(post.data.date) === year);
return (
<section class="archive-year">
<h2 id={`year-${year}`}>{year}</h2>
<ArticleList
posts={postsForYear}
showYear={false}
timeline
eagerThumbnailCount={year === years[0] ? 3 : 0}
/>
</section>
);
})
}
</Page>