Files
Vijay Janapa Reddi f8a6cdc627 fix(tinytorch): the star count was frozen at whatever the last publish saw
"28,106 stars on GitHub" is injected by inject_stats.py from
site/config/stats-cache.json at render time, so it is right when the site
is built and never again.

The main site handles this: site/index.qmd re-fetches on every page load,
both from stats.json (refreshed to gh-pages every six hours) and directly
from the GitHub API, with the comment that the star count "should track
the repo to the second rather than to the last scheduled refresh".

This site got the first half only. It emits the same
data-stat="stars" hook on two elements of the landing page but shipped
nothing to hydrate them, and it never reads stats.json at all, so a
CDN-cached page served the build-time number indefinitely. The committed
cache was generated 2026-09-14 and read 28,106; the API returned 28,258
today, 152 behind after three days.

The star count is public, so this fetches it directly rather than waiting
on a refresh cycle this site does not consume. On rate limit, offline or
a blocked request the rendered value stays, so the page always shows a
real number.

Verified in a browser: both elements read 28,106 at first paint and
28,258 after hydration.
2026-09-17 14:57:10 +02:00

32 lines
1.5 KiB
JavaScript

<script>
// Keep the GitHub star count current after deploy.
//
// inject_stats.py substitutes {{stats.stars}} at render time, so the number is
// correct at the moment the site is built and then frozen. The main site solves
// this in site/index.qmd by re-fetching on every page load; this site emitted
// the same data-stat="stars" hook but shipped nothing to hydrate it, so a
// CDN-cached page showed whatever the cache held at the last publish. The
// cached value was 152 stars behind within three days.
//
// The star count is public and needs no credential, so it is fetched directly
// from the API rather than waiting on the six-hourly stats.json refresh, which
// this site does not consume. On any failure the build-time value simply
// stays, which is why the elements are never emptied first.
(function () {
var nodes = document.querySelectorAll('[data-stat="stars"]');
if (!nodes.length) return;
fetch('https://api.github.com/repos/harvard-edge/cs249r_book')
.then(function (r) { return r.ok ? r.json() : Promise.reject(r.status); })
.then(function (d) {
if (!d || typeof d.stargazers_count !== 'number') return;
var formatted = d.stargazers_count.toLocaleString('en-US');
nodes.forEach(function (n) { n.textContent = formatted; });
})
.catch(function (err) {
// Rate limit, offline, blocked: the rendered value is still a real number.
console.warn('[tinytorch] star count refresh failed, showing build-time value:', err);
});
})();
</script>