my website
1---
2import { getCollection } from "astro:content";
3import PrettyDate from "./PrettyDate.astro";
4// import Tags from "./Tags.astro";
5import type { CollectionEntry } from "astro:content";
6
7interface Props {
8 limit?: number;
9}
10
11const { limit = Infinity } = Astro.props;
12
13const posts = (await getCollection("blog"))
14 .sort((a, b) => b.data.publish_date.valueOf() - a.data.publish_date.valueOf())
15 .slice(0, limit);
16
17type Post = CollectionEntry<"blog">;
18
19const postsByYear = Object.entries(
20 posts.reduce(
21 (acc, post) => {
22 const year = post.data.publish_date.getFullYear().toString();
23 acc[year] ??= [];
24 acc[year].push(post);
25 return acc;
26 },
27 {} as Record<string, Post[]>,
28 ),
29).sort(([year1], [year2]) => year2.localeCompare(year1));
30---
31
32<div class="posts">
33 {
34 postsByYear.map(([year, posts]) => {
35 if (!posts) return null;
36
37 return (
38 <>
39 <h3>{year}</h3>
40 <ul>
41 {posts.map(
42 ({
43 id,
44 data: {
45 title,
46 description: snippet,
47 publish_date,
48 hero_image,
49 // tags,
50 },
51 }) => (
52 <li>
53 <div class="flex gap-2 items-center">
54 <a
55 href={`/blog/${id}`}
56 class="leading-tight inline-block"
57 transition:name={`post-title-${id}`}
58 >
59 {title}
60 </a>
61 <div class="border-b border-dashed self-center flex-1" />
62 <PrettyDate date={publish_date ?? new Date()} />
63 </div>
64 <p transition:name={`post-snippet-${id}`}>{snippet}</p>
65 </li>
66 ),
67 )}
68 </ul>
69 </>
70 );
71 })
72 }
73</div>