Skip to content

Commit aa9ee28

Browse files
committed
feat: add memo releases section fetched at build time
1 parent 268174b commit aa9ee28

2 files changed

Lines changed: 163 additions & 0 deletions

File tree

src/components/Releases.astro

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
---
2+
type Release = {
3+
tag_name: string;
4+
name: string;
5+
published_at: string | null;
6+
html_url: string;
7+
body: string | null;
8+
};
9+
10+
let releases: Release[] = [];
11+
try {
12+
const res = await fetch('https://api.github.com/repos/rustkit-ai/memo/releases');
13+
const data: Release[] = await res.json();
14+
releases = data
15+
.filter((r) => r.published_at)
16+
.sort((a, b) => new Date(b.published_at!).getTime() - new Date(a.published_at!).getTime())
17+
.slice(0, 5);
18+
} catch {
19+
// silently fail
20+
}
21+
22+
function formatDate(iso: string) {
23+
return new Date(iso).toLocaleDateString('en-US', {
24+
year: 'numeric',
25+
month: 'short',
26+
day: 'numeric',
27+
});
28+
}
29+
---
30+
31+
{releases.length > 0 && (
32+
<section id="releases">
33+
<div class="section-inner">
34+
<div class="section-label reveal">Changelog</div>
35+
<h2 class="reveal">Latest releases</h2>
36+
<p class="section-sub reveal">
37+
Recent updates to <a href="https://github.com/rustkit-ai/memo" target="_blank" rel="noopener">memo</a>.
38+
</p>
39+
40+
<div class="releases-list reveal">
41+
{releases.map((r, i) => (
42+
<a href={r.html_url} target="_blank" rel="noopener" class={`release-item ${i === 0 ? 'latest' : ''}`}>
43+
<div class="release-left">
44+
<span class="release-tag">{r.tag_name}</span>
45+
{i === 0 && <span class="release-badge">Latest</span>}
46+
</div>
47+
<div class="release-name">{r.name}</div>
48+
<div class="release-date">{formatDate(r.published_at!)}</div>
49+
<span class="release-arrow">→</span>
50+
</a>
51+
))}
52+
</div>
53+
54+
<a href="https://github.com/rustkit-ai/memo/releases" target="_blank" rel="noopener" class="all-releases">
55+
View all releases →
56+
</a>
57+
</div>
58+
</section>
59+
)}
60+
61+
<style>
62+
.releases-list {
63+
display: flex;
64+
flex-direction: column;
65+
border: 1px solid var(--border);
66+
border-radius: 6px;
67+
overflow: hidden;
68+
margin-bottom: 1.5rem;
69+
}
70+
71+
.release-item {
72+
display: grid;
73+
grid-template-columns: auto 1fr auto auto;
74+
align-items: center;
75+
gap: 1rem;
76+
padding: 1rem 1.5rem;
77+
text-decoration: none;
78+
color: inherit;
79+
border-bottom: 1px solid var(--border);
80+
background: var(--bg-2);
81+
transition: background 0.2s;
82+
}
83+
84+
.release-item:last-child { border-bottom: none; }
85+
86+
.release-item:hover { background: var(--bg-3); }
87+
88+
.release-item.latest { background: var(--bg-3); }
89+
90+
.release-left {
91+
display: flex;
92+
align-items: center;
93+
gap: 0.6rem;
94+
}
95+
96+
.release-tag {
97+
font-family: 'Space Mono', monospace;
98+
font-size: 0.85rem;
99+
font-weight: 700;
100+
color: var(--text);
101+
letter-spacing: -0.02em;
102+
min-width: 60px;
103+
}
104+
105+
.release-badge {
106+
font-family: 'IBM Plex Mono', monospace;
107+
font-size: 0.62rem;
108+
padding: 0.15rem 0.45rem;
109+
border-radius: 3px;
110+
background: var(--rust-glow);
111+
color: var(--rust);
112+
border: 1px solid var(--rust-dim);
113+
letter-spacing: 0.06em;
114+
text-transform: uppercase;
115+
}
116+
117+
.release-name {
118+
font-size: 0.88rem;
119+
color: var(--text-muted);
120+
font-family: 'IBM Plex Sans', sans-serif;
121+
white-space: nowrap;
122+
overflow: hidden;
123+
text-overflow: ellipsis;
124+
}
125+
126+
.release-date {
127+
font-family: 'IBM Plex Mono', monospace;
128+
font-size: 0.75rem;
129+
color: var(--text-dim);
130+
white-space: nowrap;
131+
}
132+
133+
.release-arrow {
134+
color: var(--text-dim);
135+
font-size: 0.85rem;
136+
transition: transform 0.2s, color 0.2s;
137+
}
138+
139+
.release-item:hover .release-arrow {
140+
transform: translateX(3px);
141+
color: var(--rust);
142+
}
143+
144+
.all-releases {
145+
font-family: 'IBM Plex Mono', monospace;
146+
font-size: 0.78rem;
147+
color: var(--text-dim);
148+
text-decoration: none;
149+
transition: color 0.2s;
150+
}
151+
152+
.all-releases:hover { color: var(--rust); }
153+
154+
@media (max-width: 640px) {
155+
.release-item {
156+
grid-template-columns: auto 1fr auto;
157+
gap: 0.6rem;
158+
}
159+
.release-name { display: none; }
160+
}
161+
</style>

src/pages/index.astro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Nav from '../components/Nav.astro';
44
import Hero from '../components/Hero.astro';
55
import Projects from '../components/Projects.astro';
66
import Philosophy from '../components/Philosophy.astro';
7+
import Releases from '../components/Releases.astro';
78
import Founders from '../components/Founders.astro';
89
import Footer from '../components/Footer.astro';
910
---
@@ -13,6 +14,7 @@ import Footer from '../components/Footer.astro';
1314
<Hero />
1415
<Projects />
1516
<Philosophy />
17+
<Releases />
1618
<Founders />
1719
<Footer />
1820
</Layout>

0 commit comments

Comments
 (0)