Plan: Custom GitHub Star Badges
Plan: Custom GitHub Star Badges
Replace shields.io badges with custom-styled HTML that fetches star counts via client-side JavaScript with 24-hour localStorage caching.
Files to Modify
utils/project_listings.jl- Replace shields.io badge with HTML placeholder_css/custom.css- Add star badge styles_layout/foot.html- Add JavaScript to fetch and display star counts
Implementation
utils/project_listings.jl
utils/project_listings.jl
Replace the shields.io image badge in project_listing() with a custom HTML structure:
function star_badge(r::Repo)
return a(
:href => url_stargazers(r),
:class => "star-badge",
Symbol("data-repo") => "$(name(org(r)))/$(name(r))",
span(:class => "star-icon", "★"),
span(:class => "star-count"),
)
end
Update project_listing() to use star_badge(r) instead of the current img(:src => url_star_shield(r)) approach.
Remove url_star_shield() function (no longer needed).
_css/custom.css
_css/custom.css
Add styles in the project badges section (after line 137):
.star-badge {
display: inline-flex;
align-items: center;
gap: 4px;
color: var(--c-text-gray);
font-size: 9pt;
text-decoration: none !important;
background: none !important;
}
.star-badge:hover {
color: var(--c-text);
}
.star-icon {
color: var(--c-yellow-2);
}
_layout/foot.html
_layout/foot.html
Add JavaScript before the closing </script> tag (around line 63):
// Fetch GitHub star counts
(function() {
var badges = document.querySelectorAll('.star-badge[data-repo]');
if (!badges.length) return;
badges.forEach(function(badge) {
var repo = badge.dataset.repo;
var cacheKey = 'stars:' + repo;
var cached = localStorage.getItem(cacheKey);
if (cached) {
var data = JSON.parse(cached);
if (Date.now() - data.time < 86400000) { // 24 hours
badge.querySelector('.star-count').textContent = data.stars;
return;
}
}
fetch('https://api.github.com/repos/' + repo)
.then(function(res) { return res.json(); })
.then(function(data) {
var stars = data.stargazers_count;
badge.querySelector('.star-count').textContent = stars;
localStorage.setItem(cacheKey, JSON.stringify({
stars: stars,
time: Date.now()
}));
})
.catch(function() {
badge.querySelector('.star-count').textContent = '—';
});
});
})();
Verification
Run
serve()locallyNavigate to the projects page
Verify star badges display with correct counts
Check browser DevTools:
Network tab: GitHub API requests should fire
Application > Local Storage:
stars:org/repoentries should appear
Refresh page - stars should load from cache (no new API requests)
Verify styling matches site theme in both light and dark mode