DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on

I Built a GitHub Repo Health Scorer with the Free Public API

Hackathon judges, hiring managers, and open-source maintainers all ask the same question fast: is this repo alive and looked-after? Eyeballing every repo — commits, license, README, open issues — is slow.

So I built a tool that turns that into one number plus a fix-list. This is Day 4 of my SolveFromZero series (real problems, small tools).

One API call gives you almost everything

const r = await fetch(`https://api.github.com/repos/${owner}/${name}`);
const data = await r.json();
// stargazers_count, forks_count, open_issues_count,
// pushed_at, license, description, topics, homepage…
Enter fullscreen mode Exit fullscreen mode

No auth needed — 60 requests/hour per IP, plenty for a demo.

Turn signals into points (this is the interesting part)

Recency beats raw popularity

A repo with 50k stars last touched 3 years ago is dead. pushed_at is the strongest "maintained" signal:

const age = (Date.now() - new Date(data.pushed_at)) / 86400000; // days
const recency = age < 30 ? 20 : age < 90 ? 14 : age < 365 ? 7 : 0;
Enter fullscreen mode Exit fullscreen mode

Log-scale the stars

Linear star scoring lets torvalds/linux drown out every honest small project. Compress the range:

const popularity = Math.min(20, Math.round(Math.log10(stars + 1) * 7));
// 10★ ≈ 7 pts · 1,000★ ≈ 14 · 100k★ ≈ 20 (capped)
Enter fullscreen mode Exit fullscreen mode

Issue hygiene as a ratio

100 open issues on a 50-star repo is a red flag; 100 on a 50k-star repo is normal life. Score relative to stars, not the absolute count:

const ratio = data.open_issues_count / Math.max(stars, 1);
const issues = ratio < 0.05 ? 15 : ratio < 0.2 ? 10 : ratio < 0.5 ? 5 : 0;
Enter fullscreen mode Exit fullscreen mode

Add points for a license, a description, topics + homepage, and a README (one extra call to /repos/:o/:r/readme). Sum to 100.

Show the breakdown, not just the score

A bare number is useless. The value is "add a LICENSE for +15" and "no README". Render each component as a bar so the maintainer sees the cheapest wins:

Recent activity   ████████████████████  20/20  · pushed this month
Has license       ░░░░░░░░░░░░░░░░░░░░   0/15  · none   ← biggest quick win
Has README        ████████████████████  10/10  · yes
Enter fullscreen mode Exit fullscreen mode

The reusable shape

fetch signals → score each → sum → explain. No machine learning, no training data — just public data and transparent rules. The same shape scores npm packages, Devpost submissions, or your own portfolio repos before you ship them.

🩺 Score any public repo live: https://dev48v.infy.uk/solve/day4-repo-health.html

Day 4 of SolveFromZero. A small, real tool every day.

Top comments (0)