Based on the context from your attached files and the issue discussion, I can suggest specific edits to solve the rate limiting problem by using the Shields.io JSON API as the primary approach with GitHub API as fallback.
Use Shields.io's JSON endpoint (which provides instant cached results with no rate limit concerns) as your primary data source, with GitHub API as fallback. This approach:[1]
- Eliminates the SVG parsing hack that was initially considered[1]
- Provides faster response times than GitHub API[1]
- Avoids the rate limiting issues with high traffic[2]
- Requires no additional dependencies or cron jobs[1]
Replace your current API fetching code with this implementation:[3]
// Fetch using Shields.io JSON API (primary) with GitHub API fallback
async function fetchWithFallback(shieldsUrl, githubFetcher, fallbackValue) {
try {
// Try Shields.io JSON first (instant, cached, no rate limits)
const response = await fetch(shieldsUrl);
if (response.ok) {
const data = await response.json();
// Extract value from Shields.io JSON format
const value = data.message.replace(/,/g, '');
return isNaN(value) ? value : parseInt(value);
}
} catch (e) {
console.warn('Shields.io fetch failed, trying GitHub API', e);
}
// Fallback to GitHub API
try {
return await githubFetcher();
} catch (e) {
console.error('Both Shields.io and GitHub API failed', e);
return fallbackValue;
}
}
// Fetch downloads count
async function fetchDownloads() {
return await fetchWithFallback(
'https://img.shields.io/github/downloads/edgeleap/diffsense/total.json',
async () => {
const response = await fetch('https://api.github.com/repos/edgeleap/diffsense/releases?per_page=100');
const releases = await response.json();
let total = 0;
releases.forEach(r => {
(r.assets || []).forEach(a => total += a.download_count || 0);
});
return total;
},
0
);
}
// Fetch stars count
async function fetchStars() {
return await fetchWithFallback(
'https://img.shields.io/github/stars/edgeleap/diffsense.json',
async () => {
const response = await fetch('https://api.github.com/repos/edgeleap/diffsense');
const data = await response.json();
return data.stargazers_count;
},
0
);
}
// Fetch forks count
async function fetchForks() {
return await fetchWithFallback(
'https://img.shields.io/github/forks/edgeleap/diffsense.json',
async () => {
const response = await fetch('https://api.github.com/repos/edgeleap/diffsense');
const data = await response.json();
return data.forks_count;
},
0
);
}
// Update the UI
(async function() {
const [downloads, stars, forks] = await Promise.all([
fetchDownloads(),
fetchStars(),
fetchForks()
]);
document.getElementById('downloads-count').textContent = downloads.toLocaleString();
document.getElementById('stars-count').textContent = stars.toLocaleString();
document.getElementById('forks-count').textContent = forks.toLocaleString();
})();Shields.io advantages:[1]
- Uses authenticated GitHub tokens (5,000 requests/hour limit vs 60 unauthenticated)[1]
- Implements caching (typically 5 minutes)[1]
- Provides instant responses[1]
- Returns clean JSON format without SVG parsing[1]
GitHub API fallback:[2]
- Handles edge cases if Shields.io is temporarily unavailable
- Provides direct access to latest data when needed
- Maintains compatibility with existing error handling[3]
This solution addresses your concern about GitHub API being "kind of slow" and showing 0 values temporarily, while avoiding additional dependencies like Cloudflare or commit-heavy cron jobs.[1]