# yutao8/starred ranks one GitHub star list by seven day growth, and the two language tables disagree

> A personal GitHub bookmark repository that syncs one account's starred list, asks an LLM for a Chinese summary of each project, and publishes trend rankings across history snapshots. Its numbers are the interesting part, because the page contradicts itself on how many repositories each language has.

**yutao8/starred** — A personal collection of popular GitHub projects (1.9k+), covering frameworks, components, SDKs, templates, APIs, IPTV, scripts, crawlers, cloud-drive direct links, open-source software, tools and more.

- Repository: https://github.com/yutao8/starred
- Website: https://yutao8.github.io/starred/
- Stars: 176 · Forks: 23
- Language: HTML
- License: not declared
- Published: 2026-08-21 · Updated: 2026-08-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/yutao8-starred

## One account, one token, and a pagination ceiling of 2,000 repos

The scope is narrower than the marketing line suggests. The collection targets a single GitHub user, and the template hardcodes that user as `GITHUB_ACTOR=yutao8`. Auth is a personal access token in `GH_TOKEN`, which means the sync reads one person's star list rather than a topic, an organisation, or a search query. How much of that list gets pulled is set by three numbers, and their product is the real limit on the dataset:

```bash
REQUEST_CONCURRENCY=10
DEBUG_MODE=false
PAGE_START=1
PAGE_END=20
PAGE_LIMIT=100
RECENT_LIMIT=10
LANG_LIMIT=10
DESC_TIME=0
```

Twenty pages of one hundred is two thousand, which is exactly the 2,000-plus total the page claims at the top. The account itself is described as holding around 1.9k stars, so the ceiling is generous rather than binding, and the page width is not what you should worry about. It is that the number is a page size, not a filter. Nothing in the configuration restricts which repositories qualify, so what you get is one person's bookmarks across 57 languages, from AI tooling to IPTV lists to VPN daemons.

## DEBUG_MODE and a zero-second cache decide whether a sync is fast or stale

Two settings control cost. `DEBUG_MODE=false` is the normal setting, and turning it on restricts a run to a single page, ten repositories, and forces a full API refresh rather than a cached read. That is a sensible switch for anyone checking whether a token or a key works, because it costs a fraction of a real run. `DESC_TIME=0` is the other one, and the meaning is the opposite of what the name suggests at a glance: zero is documented as caching forever, so a summary generated once is never regenerated by later runs. Descriptions therefore do not improve over time unless someone clears that cache. `RECENT_LIMIT=10` and `LANG_LIMIT=10` cap what the front page shows rather than what is stored, and the language section of the page shows exactly ten languages for the same reason, even though it claims to cover fifty-seven. Read the caps as display settings, not as collection limits.

## Four LLM channels sit in the template, but the OpenAI one is switched off

Summaries and tags come from a large language model, and the template offers four interchangeable channels, described in the file's own comments as mutual backups. The first is OpenRouter, marked the primary channel, and it is the only one with a model list spelled out in the defaults:

```bash
# 1. OpenRouter (主渠道推荐)
OPENROUTER_KEY=
# OPENROUTER_URL=https://openrouter.ai/api/v1/chat/completions
# OPENROUTER_MODELS=openai/gpt-4o-mini,qwen/qwen-plus-2025-07-28
# OPENROUTER_CONCURRENCY=10
```

The second is DeepSeek, marked the fallback. The third, OpenAI direct, and the fourth, a custom OpenAI-compatible endpoint, are both present but every line of them, key included, is commented out. The headline feature list names DeepSeek, OpenAI and OpenRouter as the engines, while a file you copy will only prompt you for two keys. Each channel has its own commented concurrency value, which is why a separate global `REQUEST_CONCURRENCY=10` exists as a fallback when a channel leaves its own blank.

## The two language tables on the same page count different repositories

This is the flaw worth knowing about before you quote anything. The language growth table and the language distribution matrix give incompatible counts for the same languages. TypeScript appears as 149 collected repositories in the growth table and 200 in the matrix. Python is 140 and then 237. Shell is 47 and then 87, Rust is 29 and then 36. Both tables are presented as current, neither is labelled as a different snapshot, and the totals cannot be reconciled by rounding. The discrepancy is large enough to change the meaning of any ranking you build on it, because repository count is one of the inputs behind the per-language growth figures. The matrix also exposes a `NaN` bucket of 165 repositories, so a slice of the collection has no detected language at all and is filed under a string that came from a failed lookup rather than a real category.

## Two rows in the trend tables link to a repository other than the one they name

The generated tables carry a copy-paste error you can see without leaving the page. The Firecrawl row labels itself `firecrawl/firecrawl` but its hyperlink points at `mendableai/firecrawl`, which is a different owner on the same project. The growth table has the mirror image problem: the row is named `mg-chao/snow-apps` and links to `mg-chao/snow-shot`. Both are in the top five sections, so the wrong link sits in the one place a reader is bound to click. The same generation step writes the Chinese summary text into the table, so a wrong identifier does not stay cosmetic if the rows are ever machine consumed. Treat the two as evidence that the table output is assembled by string substitution rather than resolved against the GitHub API, and verify any repository link in the ranking before you use it.

## Output lands in a timestamped directory, and every link repeats the same snapshot name

The publishing layout explains itself once you see that a snapshot is a path, not a branch. Each run writes into a directory whose name is a timestamp: the links on the page all end in `data/dist/2026100118/`, which is a year, month, day and hour packed into ten digits, followed by a per-language file such as `LANG_Python.md` and a full `ALL.md` index. The trend analysis is also archived to its own timestamped directory, and each run emits a structured `trend.json` alongside a rendered `trend.md`. The three HTML pages are different: `index.html` is a searchable hall of projects by language and tag, `trend.html` is the ranking board with a snapshot browser and light and dark modes, and `history.html` draws the Star and Fork curves with ECharts. Because the timestamp is baked into the links, an older page pinned in a bookmark keeps pointing at the snapshot that was current when you bookmarked it.

## Per project history is one JSON file per repository id, diffed across runs

The historical side works by keeping a file per project and comparing versions. Each repository gets `repos/{id}.json`, and a run produces a new version of that file rather than overwriting one shared history, which is what makes the Star and Fork curves reconstructible after the fact. Three different counters are tracked per project, not just stars: the absolute total, the change since the previous snapshot, and the growth rate, and the ranking board scores them together rather than sorting on any one of them. Two filters are exposed for the growth board: a minimum star threshold, written as a `--min-stars` option, so that a project cannot win a growth ranking from a handful of stars, and a per-day average, which smooths a single large jump. Fork deltas are collected alongside star deltas, but the fork column is the one that is empty for the unclassified language bucket.

## The entry points are PHP files, and there are no releases to pin

The repository ships its own server-side code rather than a static build. The top level holds `config.php`, `fetch.php`, `trend.php`, `history.php` and a `test.php`, alongside `push.sh` and the three HTML pages, with `data/` and `assets/` holding the generated output and styling. So running it locally means serving PHP and populating a `.env`, not opening a file, and the deployment notes live in a separate `DEPLOY.md` that covers local runs and the GitHub Actions setup. The interface the pages talk to is specified in `HISTORY_API.md`, which documents the JSON API shape for reading snapshot data back out, so the trend data is meant to be consumable by something other than the bundled dashboard. Two facts about the repository itself are worth stating plainly. Its primary language is recorded as HTML, and no licence is detected, so there is no stated grant covering the summaries, the tables, or the collected metadata. The repository also has no GitHub releases, which means there is no version to pin, and the last push landed on 2026-09-30.

## Conclusion

Use starred if you want a fast, opinionated read on which GitHub projects are accelerating this week, and you can accept that the summaries are machine generated and the counts are approximate. Skip it if you need a verified ranking, a licence audit, or a reproducible dataset, since the repository publishes no releases, carries no licence, and keeps two language tallies that do not match. Before quoting a number from it, open the snapshot directory it links to, compare the two language tables, and confirm the pagination ceiling has not clipped the list you are looking at.

## FAQ

### What does yutao8/starred actually collect?

It syncs the starred repositories of one GitHub account, set to yutao8 in the example environment file, across 57 languages, with a pagination ceiling of 20 pages of 100.

### How are the Chinese summaries and tags generated?

A large language model is called while the star list is fetched. The example configuration offers four channels described as mutual backups, with OpenRouter marked primary and DeepSeek marked the fallback.

### Which LLM keys do I actually need to fill in?

Only two are left uncommented in the example file, OPENROUTER_KEY and DEEPSEEK_KEY. The OpenAI and custom OpenAI-compatible channels are present but every line of them, keys included, is commented out.

### Why do the two language tables show different repository counts?

The page gives no reconciliation. TypeScript is listed as 149 collected repositories in the growth table and 200 in the distribution matrix, Python as 140 and 237, and a further 165 repositories sit in a NaN language bucket.

## Sources

- [Official documentation](https://yutao8.github.io/starred/)
- [Official README](https://github.com/yutao8/starred#readme)
- [Project repository](https://github.com/yutao8/starred)

---

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