Skip to content

Commit d7a2f70

Browse files
Strawbangclaude
andcommitted
feat: filter private repos, dynamic releases, clean footer
- Projects: only show public repos (auto-fit grid, no empty columns) - Releases: client-side fetch (always up to date), latest release only, fix scoped styles - Footer: remove private repo links and releases link Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9048d38 commit d7a2f70

3 files changed

Lines changed: 107 additions & 81 deletions

File tree

src/components/Footer.astro

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@
1212
<div class="footer-col">
1313
<div class="footer-col-title">Projects</div>
1414
<a href="https://github.com/rustkit-ai/aimemo" target="_blank" rel="noopener">aimemo</a>
15-
<a href="https://github.com/rustkit-ai/rustkit-mcp" target="_blank" rel="noopener">rustkit-mcp</a>
16-
<a href="https://github.com/rustkit-ai/rustkit-semantic" target="_blank" rel="noopener">rustkit-semantic</a>
1715
</div>
1816
<div class="footer-col">
1917
<div class="footer-col-title">Organization</div>
2018
<a href="https://github.com/rustkit-ai" target="_blank" rel="noopener">GitHub</a>
21-
<a href="https://github.com/rustkit-ai/aimemo/releases" target="_blank" rel="noopener">Releases</a>
2219
<a href="/team">Team</a>
2320
</div>
2421
</div>

src/components/Projects.astro

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@ import { projects } from '../data/projects';
44
type Repo = { name: string; stargazers_count: number };
55
66
let repoStars: Record<string, number> = {};
7+
let publicRepoNames: Set<string> = new Set();
78
try {
8-
const res = await fetch('https://api.github.com/orgs/rustkit-ai/repos');
9+
const res = await fetch('https://api.github.com/orgs/rustkit-ai/repos?type=public&per_page=100');
910
const repos: Repo[] = await res.json();
10-
repos.forEach((r) => { repoStars[r.name] = r.stargazers_count; });
11+
repos.forEach((r) => {
12+
repoStars[r.name] = r.stargazers_count;
13+
publicRepoNames.add(r.name);
14+
});
1115
} catch {}
1216
17+
const visibleProjects = projects.filter((p) => publicRepoNames.size === 0 || publicRepoNames.has(p.slug));
18+
1319
const icons: Record<string, string> = {
1420
'aimemo': 'brain',
1521
'rustkit-mcp': 'activity',
@@ -24,7 +30,7 @@ const icons: Record<string, string> = {
2430
<p class="section-sub reveal">Open source tools designed to make AI-assisted development faster and smarter.</p>
2531

2632
<div class="projects-grid">
27-
{projects.map((p) => {
33+
{visibleProjects.map((p) => {
2834
const stars = repoStars[p.slug] ?? 0;
2935
const icon = icons[p.slug] ?? 'search';
3036
return (
@@ -83,7 +89,7 @@ const icons: Record<string, string> = {
8389
<style>
8490
.projects-grid {
8591
display: grid;
86-
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
92+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
8793
gap: 1.5px;
8894
border: 1.5px solid var(--border);
8995
border-radius: 6px;

src/components/Releases.astro

Lines changed: 97 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,88 @@
11
---
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/aimemo/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-
}
292
---
303

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/aimemo" target="_blank" rel="noopener">aimemo</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/aimemo/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 {
4+
<section id="releases" style="display:none">
5+
<div class="section-inner">
6+
<div class="section-label reveal">Changelog</div>
7+
<h2 class="reveal">Latest releases</h2>
8+
<p class="section-sub reveal">
9+
Recent updates to <a href="https://github.com/rustkit-ai/aimemo" target="_blank" rel="noopener">aimemo</a>.
10+
</p>
11+
12+
<div class="releases-list reveal" id="releases-list"></div>
13+
14+
<a href="https://github.com/rustkit-ai/aimemo/releases" target="_blank" rel="noopener" class="all-releases">
15+
View all releases →
16+
</a>
17+
</div>
18+
</section>
19+
20+
<script>
21+
function formatDate(iso: string) {
22+
return new Date(iso).toLocaleDateString('en-US', {
23+
year: 'numeric',
24+
month: 'short',
25+
day: 'numeric',
26+
});
27+
}
28+
29+
type Release = {
30+
tag_name: string;
31+
name: string;
32+
published_at: string | null;
33+
html_url: string;
34+
body: string | null;
35+
};
36+
37+
async function loadRelease() {
38+
try {
39+
const res = await fetch('https://api.github.com/repos/rustkit-ai/aimemo/releases');
40+
const data: Release[] = await res.json();
41+
const releases = data
42+
.filter((r) => r.published_at)
43+
.sort((a, b) => new Date(b.published_at!).getTime() - new Date(a.published_at!).getTime())
44+
.slice(0, 1);
45+
46+
if (releases.length === 0) return;
47+
48+
const r = releases[0];
49+
const list = document.getElementById('releases-list')!;
50+
list.innerHTML = `
51+
<a href="${r.html_url}" target="_blank" rel="noopener" class="release-item latest">
52+
<div class="release-left">
53+
<span class="release-tag">${r.tag_name}</span>
54+
<span class="release-badge">Latest</span>
55+
</div>
56+
<div class="release-name">${r.name}</div>
57+
<div class="release-date">${formatDate(r.published_at!)}</div>
58+
<span class="release-arrow">→</span>
59+
</a>
60+
`;
61+
62+
const section = document.getElementById('releases')!;
63+
section.style.display = '';
64+
65+
// Re-observe reveal elements now that the section is visible
66+
const observer = new IntersectionObserver((entries) => {
67+
entries.forEach((entry) => {
68+
if (entry.isIntersecting) {
69+
entry.target.classList.add('visible');
70+
observer.unobserve(entry.target);
71+
}
72+
});
73+
}, { threshold: 0.1 });
74+
75+
section.querySelectorAll('.reveal').forEach((el) => observer.observe(el));
76+
} catch {
77+
// silently fail
78+
}
79+
}
80+
81+
loadRelease();
82+
</script>
83+
84+
<style is:global>
85+
#releases .releases-list {
6386
display: flex;
6487
flex-direction: column;
6588
border: 1px solid var(--border);
@@ -68,7 +91,7 @@ function formatDate(iso: string) {
6891
margin-bottom: 1.5rem;
6992
}
7093

71-
.release-item {
94+
#releases .release-item {
7295
display: grid;
7396
grid-template-columns: auto 1fr auto auto;
7497
align-items: center;
@@ -81,19 +104,19 @@ function formatDate(iso: string) {
81104
transition: background 0.2s;
82105
}
83106

84-
.release-item:last-child { border-bottom: none; }
107+
#releases .release-item:last-child { border-bottom: none; }
85108

86-
.release-item:hover { background: var(--bg-3); }
109+
#releases .release-item:hover { background: var(--bg-3); }
87110

88-
.release-item.latest { background: var(--bg-3); }
111+
#releases .release-item.latest { background: var(--bg-3); }
89112

90-
.release-left {
113+
#releases .release-left {
91114
display: flex;
92115
align-items: center;
93116
gap: 0.6rem;
94117
}
95118

96-
.release-tag {
119+
#releases .release-tag {
97120
font-family: 'Space Mono', monospace;
98121
font-size: 0.85rem;
99122
font-weight: 700;
@@ -102,7 +125,7 @@ function formatDate(iso: string) {
102125
min-width: 60px;
103126
}
104127

105-
.release-badge {
128+
#releases .release-badge {
106129
font-family: 'IBM Plex Mono', monospace;
107130
font-size: 0.62rem;
108131
padding: 0.15rem 0.45rem;
@@ -114,7 +137,7 @@ function formatDate(iso: string) {
114137
text-transform: uppercase;
115138
}
116139

117-
.release-name {
140+
#releases .release-name {
118141
font-size: 0.88rem;
119142
color: var(--text-muted);
120143
font-family: 'IBM Plex Sans', sans-serif;
@@ -123,39 +146,39 @@ function formatDate(iso: string) {
123146
text-overflow: ellipsis;
124147
}
125148

126-
.release-date {
149+
#releases .release-date {
127150
font-family: 'IBM Plex Mono', monospace;
128151
font-size: 0.75rem;
129152
color: var(--text-dim);
130153
white-space: nowrap;
131154
}
132155

133-
.release-arrow {
156+
#releases .release-arrow {
134157
color: var(--text-dim);
135158
font-size: 0.85rem;
136159
transition: transform 0.2s, color 0.2s;
137160
}
138161

139-
.release-item:hover .release-arrow {
162+
#releases .release-item:hover .release-arrow {
140163
transform: translateX(3px);
141164
color: var(--rust);
142165
}
143166

144-
.all-releases {
167+
#releases .all-releases {
145168
font-family: 'IBM Plex Mono', monospace;
146169
font-size: 0.78rem;
147170
color: var(--text-dim);
148171
text-decoration: none;
149172
transition: color 0.2s;
150173
}
151174

152-
.all-releases:hover { color: var(--rust); }
175+
#releases .all-releases:hover { color: var(--rust); }
153176

154177
@media (max-width: 640px) {
155-
.release-item {
178+
#releases .release-item {
156179
grid-template-columns: auto 1fr auto;
157180
gap: 0.6rem;
158181
}
159-
.release-name { display: none; }
182+
#releases .release-name { display: none; }
160183
}
161184
</style>

0 commit comments

Comments
 (0)