# Best of JS: a self-hostable monorepo for tracking JavaScript project trends

> Best of JS is the open source monorepo behind bestofjs.org, a curated database of about 2000 web and Node.js projects whose GitHub star counts are refreshed by a scheduled task. This review covers its four-app layout, how to run it locally with Docker and pnpm, and where the documentation stops short.

**bestofjs/bestofjs** — :star: A place to find the best components to build amazing web applications. The best of JavaScript!

- Repository: https://github.com/bestofjs/bestofjs
- Website: https://bestofjs.org
- Stars: 3,136 · Forks: 162
- Language: JavaScript
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/bestofjs-bestofjs

## What Best of JS tracks, and who the monorepo is actually for

Best of JS is a directory of open source projects related to the web platform and Node.js. The README describes the scope as JavaScript and TypeScript on both client and server, plus HTML, CSS, languages that compile to JavaScript, and alternative runtimes such as Deno and Bun. Projects sit under curated tags: component toolkits, UI frameworks, Node.js frameworks, charting libraries, and more. The public site is the product most people know. The repository is the machinery behind it.

The README states that the project maintains a list of interesting projects in a database, that a scheduled task checks project data from GitHub every day, and that the web application displays star variations over the last days, weeks and months. The README puts the curated list at about 2000 projects.

That framing tells you who the monorepo is for. It is for someone who wants to run that pipeline themselves: a team building an internal directory of approved dependencies, a maintainer who wants a trends view over a narrower ecosystem, or a developer who wants to read a real Next.js and Postgres codebase rather than a tutorial. It is not a library you import. There is no npm package called bestofjs that you add to an application, and the README never suggests one.

The classification is manual and editorial, which is the point and also the cost. A curated list of roughly 2000 entries is a different artefact from a keyword search over GitHub. It gives you a stable taxonomy and it gives you whatever the maintainers decided to include. If your stack includes a project nobody added, the trends view simply will not show it until someone opens an issue. The README points contributors at a GitHub issue template for suggesting a project, which is the documented path in.

## Four applications, two packages, and a daily GitHub ingestion job

The README shows the repository layout directly: an apps directory containing admin, backend, web and legacy, and a packages directory containing api and db. That is the architecture in one glance. The web app renders the public site. The backend owns scheduled work and data ingestion. The admin app is the editorial surface. The legacy app is excluded from the main build, lint and typecheck scripts, which all pass -F=!legacy to turbo.

The data flow described in the README is a daily loop: a scheduled task reads project data from GitHub, the result is stored in a database, and the web application consumes that stored data to compute star variations. The repository's backup script at apps/backend/src/backup/make-backup.ts and its matching restore script confirm that the database is treated as the durable state. That is a meaningful design choice. The site is a view over a database, not a view over live GitHub API responses, which is why a page can show a delta over weeks and months at all.

The db package holds that state, and docker-compose.yaml shows what it runs on: postgres:17.4 with a database named bestofjs-dev, plus a WebSocket proxy image, ghcr.io/neondatabase/wsproxy:latest. The comment above the proxy service explains why it exists: to mimic the serverless nature of Vercel Postgres during local development, so that @vercel/postgres connects the same way it would in production. That is a thoughtful detail. It also means your local setup is modelling a specific hosting provider's connection semantics rather than plain TCP, and anyone who swaps Postgres for another database has to reckon with that proxy.

The tooling layer is Turbo with pnpm workspaces. The root package.json declares packageManager pnpm@11.0.8 and engines of node >=24 and pnpm >=11. Those are hard floors, not suggestions, and they are the first thing to check against your build environment.

## Running Best of JS locally: Docker, pnpm, and the first commands

The README does not include a step-by-step install section, so the entry points below come from the repository files themselves: docker-compose.yaml, the root package.json scripts, and the workspace configuration. Treat this as the documented surface rather than a verified walkthrough.

Start the database. The compose file exposes Postgres on host port 54320 and the WebSocket proxy on 54330, and it creates a named volume under db-data. Both ports must be free before you begin.

```bash
docker compose up -d
```

After this, docker compose ps should show two running services, postgres and pg_proxy. The comment in the file notes that the db-data folder does not need to be created manually, because Docker Compose will do it.

Install dependencies at the repository root. The packageManager field pins pnpm 11, and the engines field requires Node 24 or newer, so check node --version before running this.

```bash
pnpm install
```

Build the workspace. The build script runs Turbo across all packages except legacy.

```bash
pnpm build
```

The remaining scripts are the ones you will reach for most often. pnpm lint runs Biome through Turbo, pnpm typecheck runs TypeScript, and pnpm test runs the web package's test suite. End-to-end tests need a one-time browser install before pnpm test:e2e will work.

```bash
pnpm test:e2e:install
pnpm test:e2e
```

There is also a CLI entry point, exposed as pnpm cli, which loads a dotenv file for the stage named by the STAGE variable (development by default) and runs apps/cli/src/cli.ts under Bun. The README does not document the CLI's subcommands, so you will need to read the source to learn what it accepts. That gap is worth knowing about before you plan any automation around it.

## Where the documentation stops and the risk begins

The README is a concept document, not an operations manual. It explains what Best of JS is, how projects are tagged, and that a daily task refreshes GitHub data. It does not explain how to deploy, how the scheduled task is triggered in production, what environment variables the backend expects, or how to roll back a bad ingestion run. The backup and restore scripts exist in the repository, but the README does not describe when to run them or what a restore does to existing data.

The release history is the second constraint. The most recent tagged release is v0.37 from 2023-08-03, preceded by v.0.36.0 on 2022-08-28 and v0.35.0 on 2022-05-25. The repository's last push was on 2026-09-23, so work is happening on the develop branch, but the tags have not kept pace. If you depend on releases as your upgrade unit, you are depending on something the project has not refreshed in a long time, and you should plan to track the develop branch instead.

A third limit is scope. The README places the curated list at about 2000 projects covering the web platform and Node.js. That is a deliberate boundary. Rust crates, Python packages or mobile SDKs are out of scope by construction, and the tagging taxonomy is built around front-end and Node categories. If your dependency review spans multiple ecosystems, this is the wrong tool and no configuration will fix it.

Finally, the README describes a scheduled task without specifying its scheduler. That is the piece most likely to surprise anyone self-hosting, because the freshness of every star delta depends on it. The documentation is silent here, and you should treat that silence as work you own.

## Best of JS compared with a general-purpose dependency tracker

The closest alternative in kind is a tool like Libraries.io, which aggregates package metadata across many registries and languages and exposes it through an API. The difference is the axis of measurement. Libraries.io answers questions about releases, dependency graphs and licences across ecosystems. Best of JS answers a narrower question: which web and Node.js projects are gaining or losing GitHub stars over days, weeks and months, among a hand-picked list. One is breadth of metadata, the other is a curated trend signal.

A second comparison is simply querying GitHub yourself. You can call the GitHub API for star counts on any repository, and for a handful of projects that is the right answer. What the Best of JS pipeline adds is the curated list, the tag taxonomy, and stored history. Star deltas need a previous value to subtract from, and the README's daily task is what produces that series. Building the same thing yourself means writing the scheduler, the schema, the backfill and the site. That is the work this monorepo has already done.

The trade-off is control. Running Best of JS means running Postgres, a WebSocket proxy, four applications and a Turbo build on Node 24 with pnpm 11. For a team that only wants a monthly report on a dozen dependencies, that footprint is hard to justify, and a scheduled script writing to a spreadsheet will do the job. The monorepo earns its keep when you want a browsable, tag-organised trends surface that others on your team will actually open.

## Licence and the real cost of keeping a fork current

The repository is MIT licensed, and the root package.json repeats that as "license": "MIT". For a self-hosted internal deployment, MIT is permissive: you can run it, modify it and keep your changes private. Two things are worth checking yourself rather than assuming. The first is whether the data you ingest carries separate terms. The pipeline reads project data from GitHub, and how you may store and republish that data is governed by GitHub's terms, not by this repository's licence. The second is third-party assets. The README links sponsor and backer images from Open Collective, and those are external services. If you fork the site, you are responsible for what your deployment embeds.

The upgrade cost is the more practical concern. Dependencies are pinned through a pnpm lockfile and a catalog mechanism (several devDependencies use "catalog:" rather than explicit versions), and the workspace is driven by Turbo. That means a version bump is rarely a one-line change; it is a lockfile update plus a Turbo run across the packages. The Node 24 and pnpm 11 engine floors will move as the project moves, and nothing in the README promises a compatibility window. Because the latest tag predates the current develop branch by years of commits, a fork that tracks releases will drift quickly from a fork that tracks develop. Pick one and be explicit about it.

## Conclusion

Adopt the Best of JS monorepo if you want a working reference for a Next.js plus Postgres trend tracker, or if you intend to run a curated project directory of your own under the MIT licence. Do not adopt it if you need a supported product with a stable API: the last tagged release is v0.37 from 2023-08-03, and the README documents neither the deployment pipeline nor a rollback path. Before committing, verify three things in your own checkout: that the Node 24 and pnpm 11 engine constraints match your CI, that the docker-compose Postgres and WebSocket proxy ports 54320 and 54330 are free, and that the admin and backend applications give you the ingestion controls you need, since the README does not describe their permissions model.

## FAQ

### What is Best of JS and how does it decide which projects to list?

Best of JS is a site and monorepo that gathers trends about open source projects related to the web platform and Node.js. The README states that a curated list of about 2000 projects is maintained in a database, and that projects are classified under tags such as component toolkits, UI frameworks, Node.js frameworks and charting libraries. The README points contributors at a GitHub issue template for suggesting a project.

### How do I run the Best of JS monorepo locally?

The repository ships a docker-compose.yaml that starts Postgres 17.4 with a database named bestofjs-dev on port 54320, plus a WebSocket proxy on port 54330. From there you install with pnpm and build with Turbo, using the root scripts. The README itself does not contain a step-by-step local setup guide, so the compose file and package.json are the sources to follow.

### How often does Best of JS refresh its GitHub data?

The README states that every day a scheduled task checks project data from GitHub and generates the data consumed by the web application. The web application then displays star variations over the last days, weeks and months. The README does not name the scheduler that triggers the task.

### What are the top 5 JavaScript libraries?

The README does not publish a ranking of individual libraries. It describes how projects are classified under tags such as component toolkits, UI frameworks, Node.js frameworks and charting libraries, and names D3, ChartJS and ECharts as charting examples, but it stops short of a top-five list.

### Is Best of JS actively maintained?

The repository is not archived, and its last push was on 2026-09-23. The most recent tagged release, however, is v0.37 from 2023-08-03, so the tags and the develop branch have diverged significantly. Judge adoption against the branch you intend to track.

## Sources

- [bestofjs/bestofjs on GitHub](https://github.com/bestofjs/bestofjs)
- [License: MIT](https://github.com/bestofjs/bestofjs/blob/develop/LICENSE)
- [Project website](https://bestofjs.org)
- [README](https://github.com/bestofjs/bestofjs/blob/develop/README.md)
- [Releases](https://github.com/bestofjs/bestofjs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bestofjs-bestofjs
