BETAmodules.com is in beta — open to partnerships & joint ventures.Build with us
Methodology

How Modules works

Every package is reduced to five normalized axes plus a plain-language verdict. The rules below are how those signals are computed — transparent, inspectable, and the same across every ecosystem.

Why share the rules? Because developers will challenge wrong verdicts. We want you to be able to point at a specific bucket threshold and say “that’s wrong” rather than wonder if there’s a black box behind it. There isn’t.

1

Maintenance — is this package alive?

We derive a maintenance signal from the time since the latest publish, refined by the source repository’s status when it’s on GitHub. The buckets:

  • Healthy — latest publish under 6 months ago.
  • Aging — latest publish 6 to 18 months ago. Worth checking the repo for activity before adopting.
  • Abandoned — latest publish over 18 months ago.
  • Deprecated / Archived — the maintainer marked the package deprecated on the registry, or the source repo is archived/disabled on GitHub. This overrides recency: a deprecated package is always treated as risk even if it just published.

When we have GitHub data for the source repo, an additional rule fires: if npm publishes look healthy but the repo hasn’t been pushed in 18+ months, we downgrade to Aging. Catches packages that get rare maintenance releases on a dead upstream.

2

Popularity — is it widely trusted?

Popularity uses weekly downloads, bucketed into four ranks within each ecosystem. We never compare raw download counts across ecosystems — npm and PyPI report downloads completely differently and the absolute numbers are meaningless side by side. The rank label is the cross-ecosystem comparable, not the raw number.

The bucket thresholds we use:

EcosystemTop 1%Widely usedRisingNiche
npm≥ 10M / wk≥ 500K / wk≥ 20K / wkbelow
PyPI≥ 5M / wk≥ 250K / wk≥ 10K / wkbelow
crates.io≥ 500K / wk≥ 50K / wk≥ 5K / wkbelow
RubyGems≥ 2M / wk≥ 100K / wk≥ 10K / wkbelow
Go≥ 500K / wk≥ 50K / wk≥ 5K / wkbelow
Maven≥ 1M / wk≥ 50K / wk≥ 5K / wkbelow
NuGet≥ 5M / wk≥ 100K / wk≥ 5K / wkbelow

Maven, NuGet and Go don’t publish a public weekly-downloads number, so popularity shows Unknownfor those today. We’ll add dependent-count based ranking later.

3

Security — is it safe to use?

Security is pulled live from OSV.dev, Google’s open-source vulnerability database. We query for advisories that apply to the package’s latest version specifically — so a package with old CVEs that were fixed in the current release shows Clean.

  • Clean — no advisories apply to this version.
  • N advisories with a HIGH severity pill — at least one advisory is rated CRITICAL or HIGH by GHSA. Treated as the worst signal and overrides the verdict.
  • N advisories with a MEDIUM pill — worst is rated MODERATE.
  • N advisories with a LOW pill.
  • Unchecked— the OSV call itself failed (rate limit, network). We never silently show “Clean” when we couldn’t actually check.

Each advisory listed on the detail page links to its OSV record. The severity comes from the GHSA database_specific.severity field; OSV entries without a textual severity fall back to CVSS score parsing (which often resolves to Unknownsince we don’t evaluate full CVSS vectors yet).

4

License — can I use it?

The license SPDX string is classified into three buckets — the actual SPDX is always shown alongside so you see exactly what the package declared.

  • Permissive — MIT, ISC, BSD-2/3-Clause, Apache-2.0, Unlicense, CC0-1.0, 0BSD. Generally safe for commercial use.
  • Copyleft — GPL, AGPL, LGPL, MPL-2.0, EPL-2.0. May require you to release your project under the same terms; review compatibility before adopting.
  • Other— anything we don’t recognise (custom, proprietary, unusual). Worth reading the actual license.

For OR-style SPDX expressions like (MIT OR Apache-2.0)we classify on the first license. We don’t give legal advice — “safe for commercial use” is a heuristic, not a clearance.

5

Dependencies — how heavy is it?

Counts direct runtime dependencies only. Peer and dev dependencies don’t ship, so they don’t count toward weight.

  • Lean— 0–4 direct deps. “Zero deps” gets a special label when count is 0.
  • Moderate — 5–14 direct deps.
  • Heavy — 15+ direct deps. Flagged in the verdict as a tradeoff.
6

The verdict — plain language

The verdict line at the top of every card and detail page is rule-based, not AI-written (the AI version is Phase 5 and deferred). The opener comes from the popularity rank when the package is healthy:

  • Top 1%→ “Safe default. Widely trusted across the ecosystem.”
  • Widely used→ “Solid choice. Well-adopted and active.”
  • Rising→ “Worth a look. Actively maintained and growing.”
  • Niche→ “Maintained. Niche but maintained.”

A HIGH-severity advisory overrides the opener with a security-led verdict (“Has N high-severity advisories. Verify a patched version exists before using”). Aging or abandoned packages get a maintenance-led verdict. Deprecated packages get “Deprecated. Don’t start a new project on this.”

The catch line below the verdict appends caveats: copyleft license, heavy dep tree, moderate-severity open advisories. Everything in the verdict can be traced back to a specific rule in src/lib/normalize.ts.

7

Data sources

Every signal comes from a public, free data source. Nothing is scraped:

  • npm registry — search and package metadata (registry.npmjs.org) + the downloads API (api.npmjs.org).
  • PyPI JSON API — exact-name package metadata. PyPI has no public free-text search, so we look up by exact name only.
  • pypistats.org — weekly downloads for PyPI packages.
  • crates.io API — search and metadata, including 90-day downloads.
  • RubyGems API — search, metadata and per-version downloads.
  • NuGet Azure Search — search index for the .NET ecosystem.
  • Maven Central Solr — search and version metadata.
  • deps.dev— Google’s aggregated cross-ecosystem metadata. Backbone for Go, Maven, NuGet, plus license, advisory IDs and direct-dep counts everywhere.
  • OSV.dev — security advisories across every ecosystem.
  • GitHub API — repo stars, open-issue count, archived/disabled flag, last push. Used to refine the maintenance signal on detail pages.

Everything is cached at the fetch layer (1 hour for metadata, 6 hours for downloads and GitHub, 24 hours for OSV). We don’t hammer upstream registries.

8

What we don't do (yet)

  • No AI features. Natural-language search and AI-written verdicts are Phase 5, deferred. The deterministic rule engine is what ships today.
  • No legal advice. The license classification is a developer heuristic, not a clearance from counsel.
  • No CVSS-vector scoring.We use GHSA’s textual severity. Most npm/PyPI advisories have it; the few that don’t show as Unknown.
  • No transitive-dependency analysis. We count direct runtime deps only — not the full dependency tree.
  • Maven, NuGet and Go don’t expose download counts publicly, so popularity for those ecosystems is currently Unknown.
  • No yanked-version awareness for npm.npm doesn’t expose yanks the way PyPI does. We pick up explicit deprecations.

Found a wrong verdict? Tell us — partners@modules.com or open an issue on the repo. The rules are explicit so they can be fixed.