Skip to content

Full Stack · Developer Tools

RepoSignal

Software that evaluates how software is being engineered.

  • 477 tests + 22 e2e specs
  • deterministic scoring
  • MIT
RepoSignal analyzing react/react: an overall score of 86/100, seven category scores, and a banner explaining that branch protection could not be retrieved
react/react scored 86/100 — with branch protection reported as unverifiable, not failed

01The problem

Star counts measure popularity, not health.

Judging an unfamiliar repository usually means skimming the README, glancing at the commit graph, and guessing. Most “repo score” tools replace the guess with a number you cannot interrogate — which is worse, because it looks like knowledge.

RepoSignal is built on the opposite premise: a score you cannot audit is not worth showing. Every category expands to reveal the metrics examined, their raw values, the weights applied, the thresholds used, and links to the evidence on GitHub.

02The rule that shaped the architecture

Missing data is not evidence of poor health.

A repository whose commit statistics GitHub has not computed is not unhealthy — it is unmeasured. So an unobservable metric is null, a category with too little data scores null rather than zero, and a null category is excluded from the overall score with its weight redistributed.

Silently turning missing data into a zero is the easiest way to make a health score dishonest. Avoiding it drove most of the type design — score: number | null appears throughout, and the UI renders “insufficient data” rather than a fabricated number. The invariant is enforced by a test: adding a null category can never lower the overall score.

03How an analysis happens

01

GitHub REST API

auth · retry · timeouts · request budget

A hand-written client collects public evidence — commits, pull requests, issues, workflow runs, community files — under a hard per-analysis request budget. Rate limits fail fast with a reset time instead of retrying into the wall.

02

Normalization

GitHub payloads → domain types

GitHub response shapes never escape this layer. Nothing downstream references a GitHub field name, so an API change is contained to one directory — and the scoring engine can be tested with plain object literals instead of recorded HTTP fixtures.

03

RepositorySnapshot

the only input scoring ever sees

Everything observable about the repository lands in one immutable snapshot. If a metric could not be observed, it is null here — not zero, not a default. That distinction survives all the way to the screen.

04

Scoring engine

pure functions per category

Seven categories score the snapshot with documented weights and thresholds. A category without enough data scores null and is excluded, its weight redistributed. A test asserts the invariant directly: adding a null category can never lower the overall score.

05

Explainable result

versioned · serializable · cacheable

The UI calculates nothing. Every number on screen expands into the metrics examined, the raw values, the weights applied, and links back to the evidence on GitHub.

04What it measures

What it measures

Repository activity

Commit cadence, last push, release recency and regularity

Pull request health

Open PR ages, merge velocity, long-lived open PRs

Issue health

Backlog age, stale issues, open/close rates

CI health

Workflows present, recent run outcomes, repeated failures

Documentation

README, CONTRIBUTING, LICENSE, templates, docs directory

Repository hygiene

Lockfiles, CODEOWNERS, dependency automation, release tags

Security hygiene

SECURITY.md, dependency automation, scanning in CI

Deliberately “hygiene”, not “security score”

RepoSignal observes practices; it does not scan for vulnerabilities and will never claim a repository is secure. A test collects every user-facing string in that module and asserts none of them says so.

05Engineering decisions

Engineering decisions

Deterministic scoring instead of an LLM
The same snapshot always yields the same result, every threshold can be unit tested, and a user who disagrees can be shown the exact rule that produced the number. An LLM-generated score is none of those things — AI stays a possible presentation layer, never the calculator.
A hand-written GitHub client instead of Octokit
Three policies shaped the client’s public signatures: a hard per-analysis request budget, sample truncation surfaced to the caller (paginate returns { items, truncated }), and rate-limit handling that fails fast with a reset time. Expressing those on top of a general-purpose client meant fighting it.
Repository identity is the numeric ID
Repositories get renamed and transferred — while building this, facebook/react became react/react. GitHub’s numeric id is the stable identity, so a rename resolves cleanly instead of forking history into two records.
A strict CSP, paid for honestly
Next.js streams Suspense boundaries through inline scripts, which a strict script-src blocks. RepoSignal takes a per-request nonce and gives up prerendering, since nonces are injected at render time. A real trade, recorded as one rather than presented as a free win.
No charting library
The charts are static distributions. Server-rendered SVG ships zero client JavaScript and makes the accessible text alternative part of the markup rather than a retrofit.
Private repositories via a GitHub App, not OAuth
A classic OAuth app would demand the repo scope — read and write — on everything. A GitHub App grants read-only access to explicitly selected repositories. Tokens are minted per use, expire in an hour, and never touch the database or a log.

06Testing

No test contacts the live GitHub API.

477 unit, integration and component tests plus 22 Playwright specs run against MSW-mocked responses and bundled fixture snapshots — an unhandled request fails the test rather than escaping. CI is therefore immune to rate limits and outages.

  • Unit — every threshold and null path, in isolation
  • Integration — the layers compose, network mocked with MSW
  • Component — every UI state renders correctly
  • E2E — the journey works in a browser, against a real build

07The methodology, on screen

The methodology, on screen

RepoSignal's expanded methodology for Repository Activity, listing each scoring component with its rule, score, weight, and observation
Every category expands to its rules, weights, and observations
Distribution charts in RepoSignal rendered as server-side SVG with accessible text alternatives
Distributions as server-rendered SVG — zero client-side charting code
RepoSignal's home page: a single input asking for a repository like facebook/react, with recent analyses beneath it
The whole product fits in one question: which repository?

08Stack and links

Stack and links

Next.js 16 (App Router) · React 19 · TypeScript strict with noUncheckedIndexedAccess and exactOptionalPropertyTypes · Tailwind CSS 4 · PostgreSQL + Prisma · Zod · Vitest · React Testing Library · Playwright · MSW · GitHub Actions.

Repository · Live demo · Scoring methodology · Architecture notes