Commit Graph
99 Commits
Author SHA1 Message Date
Vinta ChenandClaude fc0fda7fa7 feat: link repos in the star-scan ledger with full GitHub URLs
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 21:46:27 +08:00
Vinta ChenandClaude 66e177d983 fix: prune star-scan ledger rows for repos no longer starred
The ledger kept screen-out rows for unstarred repos because the scan script only read it and the skill called it append-only, so dead rows piled up.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-08 21:42:57 +08:00
Vinta ChenandClaude 4d9814a625 fix: ignore global git config in sitemap lastmod test commits
The sitemap lastmod test failed wherever the global git config enabled commit signing with an unreachable key, because the test strips every GIT_* variable and so dropped any override that disabled signing.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-31 22:28:17 +08:00
Vinta ChenandClaude 038f184473 build: replace httpx with httpx2 in website scripts
httpx has had no release since December 2024.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-31 22:21:52 +08:00
Vinta ChenandClaude b91f2ab950 style: highlight Sponsorship in the topbar instead of Submit a project
The navbar gave Submit a project the highlighted style that marks the main call to action.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-27 20:56:58 +08:00
Vinta ChenandClaude a348248251 test: remove entry links test
The test ran main.js against a hand-built fake page, so any new browser API main.js used at page load broke it with a TypeError unrelated to entry links.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-27 20:51:19 +08:00
Shubham Padkonde ee9dfa0d8e fix(website): open entry anchors after restoring filters 2026-10-27 17:36:05 +05:30
Vinta ChenandClaude d58e8d835a refactor: remove comments that restate the code under website/
Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-26 12:08:16 +08:00
Vinta ChenandClaude b039f790ca feat: keep only the lead above the table for an intro without a pick list
An intro without a "How to choose" list, as a one-project category has no picks to compare, rendered all of its guide paragraphs above the table, pushing the table down. It now shows the lead above the table and moves the rest into the guide.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 23:13:13 +08:00
Vinta ChenandClaude 9177a2e8a7 fix: link full project names in intro picks that matched only part
Nine picks, such as "OpenAI Agents SDK", "MCP Python SDK", and "Jupyter Notebook", linked only part of the name or nothing, because the README lists those projects under their PyPI or repo names. The punctuation-guard test used "The Algorithms - Python", which now matches its alias in full, so it uses a made-up name instead.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 22:44:16 +08:00
Vinta ChenandClaude 262d914e5d fix: correct site copy that described a tag filter and mixed terminology
Copy told visitors to tap a tag to filter and mentioned a filter although tags are plain links and no filter exists; casing and terminology were inconsistent.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 22:35:14 +08:00
Vinta ChenandClaude 786ebb4c78 feat(website): show the sponsor band on category pages
The sponsor band rendered only on the homepage, so visitors who entered on a category page and never opened the homepage saw no sponsors. Category, subcategory, group, and Stdlib pages now show the same band between the hero and the table.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 09:09:22 +08:00
Vinta ChenandClaude 69d35b2462 feat: tag sponsor links with UTM parameters
Sponsor links carried no UTM tags, so sponsors saw awesome-python clicks at best as generic referral traffic and could not tell README clicks from website clicks. README sponsor entries now carry utm_source=awesome-python&utm_medium=sponsorship&utm_campaign=sponsor&utm_content=readme, and the website build rewrites utm_content to website for the sponsor band. New sponsor entries in README.md need the same UTM suffix.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 09:09:22 +08:00
Vinta ChenandClaude d78d1f1a2f fix: isolate sitemap lastmod test from inherited GIT_* variables
The test ran git init/add/commit with the inherited environment, so under a git hook or `git rebase --exec` (which set GIT_DIR) it committed fixture commits into the real repository and flipped its core.bare to true.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-21 09:08:27 +08:00
Vinta ChenandClaude 1ebff58bf9 feat: link category intro picks to their table rows
Picks in a "How to choose" list were plain text, so a reader had to hunt for the tool's row in the table.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-16 19:45:38 +08:00
Vinta ChenandCodex 32ac8c9b3c fix: reopen parked projects in incremental star scans
Parking a project during a full review left its previous screen-out or rejection active, so incremental scans hid it instead of revisiting it.

Co-Authored-By: Codex <noreply@openai.com>
2026-10-16 19:18:59 +08:00
Vinta ChenandCodex 3827f0e622 fix: preserve review row kind when parking a verdict
Seeding an uncertain addition or listed entry as park erased its row kind, so review offered structure actions and exported the wrong verdict.

Co-Authored-By: Codex <noreply@openai.com>
2026-10-16 19:17:28 +08:00
Vinta ChenandClaude 170882bff5 refactor: fix lint findings from ruff 0.16 default rules
Ruff 0.16 enables 413 default rules (up from 59), so make lint failed with 11 findings, and it treated website/ modules as third-party.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-10 18:57:54 +08:00
Vinta ChenandClaude f6c80bf440 fix: drop noindex from category redirect stubs
Redirect stubs for renamed category URLs carried a robots noindex meta, so Search Console filed them under "Excluded by 'noindex' tag" instead of treating the instant meta refresh as a permanent redirect, and the old URLs' ranking was not passed to the new pages.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-07 18:36:19 +08:00
Vinta ChenandClaude 38a4641e09 feat: improve subcategory page titles and meta descriptions
Subcategory titles such as "JWT for Authentication" lacked searchable words, and their boilerplate descriptions never named the listed projects and said "1 projects".

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 19:54:02 +08:00
Vinta ChenandClaude 3643d6d657 fix: derive sitemap lastmod from git history instead of build date
Every sitemap URL got the build date as lastmod, so all pages claimed a change on each daily deploy, and the sponsorship page used file mtime, which on CI's fresh checkout is also build time.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 19:48:50 +08:00
Vinta ChenandClaude c16dae14ef feat: show section intro lead on group pages
Group pages showed only tables, so visitors arriving from broad searches like "python ml library" got none of the which-one-to-pick guidance that each section's intro already gives.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 19:35:04 +08:00
Vinta ChenandClaude 775caf6a1e fix: stop repeating Python in group page titles
Group pages whose names start with "Python" got titles like "Python Python Language Libraries" in the title, og:title, and JSON-LD name.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 14:45:44 +08:00
Vinta ChenandClaude 2aa87f880b fix: drop doubled noun from category page titles
Category names ending in a plural noun (DevOps Tools, Web Frameworks, HTTP Clients, Stdlib) got titles like "Python DevOps Tools Libraries" in title, og:title, twitter:title, and JSON-LD name.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 14:44:13 +08:00
Vinta ChenandClaude f0ebe92155 fix: order category page JSON-LD ItemList to match rendered rows
Category pages' JSON-LD ItemList listed entries in download order while the table renders them in README (editorial) order, so structured-data positions didn't match the visible rows.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-27 14:47:00 +08:00
Vinta ChenandClaude 5b80c4ef6b fix: point description cross-reference links at category pages
Category pages render each README section's description as-is, so cross-reference links inside it pointed at README anchors (#package-management on Build Tools, #web-apis on Web Frameworks) that don't exist on those pages and led nowhere.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-27 09:10:59 +08:00
Vinta ChenandClaude 77b1b70df5 fix: hide use-case and page tags that repeat the group heading
On section and subcategory pages, every row repeated its use case and current page as tags (and as the label under the name on phones), right under a heading that already said the same thing. They are now hidden in editorial order and shown again when a column sort flattens the groups.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-27 02:05:18 +08:00
Vinta ChenandClaude 52915911d4 feat: link section use-case headings to their subcategory pages
With tags now pointing at section anchors instead of filtering in place, subcategory pages (74 clicks and 19.7K impressions in the last 3 months) had no other internal links pointing to them.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-27 00:34:07 +08:00
Vinta ChenandClaude 62a4e7c4e5 fix: make tags link to category pages instead of filtering in place
Clicking a category or group tag filtered the homepage table in place while rewriting the address bar to the category URL, so one URL rendered two different pages and readers never reached category pages with their intros and guides; category pages also showed a redundant self-referential filter bar.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-27 00:34:07 +08:00
Vinta ChenandClaude 2b9469c0ae feat: group category page rows by use case, restructure intro
Category pages sorted rows by downloads, which buried editorial leads (the Django ORM showed as row 7 of 7, tkinter as 14 of 14) against CONTRIBUTING.md's "position is the marker"; the full intro in the hero pushed the table 2.5 screens down on a phone; and every page repeated the same "Search every project in one place" H2.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-26 23:33:57 +08:00
Vinta ChenandClaude 9cc721f533 fix: match category meta titles to search query word order
Category page titles read "ORM Python Libraries", but people search "python orm", so the title word order didn't match the query.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-26 23:28:51 +08:00
Vinta ChenandClaude a74ca52860 feat: render per-category intro text above the entry list
Category pages carried no text of their own beyond the README one-line description, and most meta descriptions fell back to a generic "Explore N curated Python projects" line, which correlated with weak search rankings for category queries. This adds optional per-category intro markdown files rendered under the H1, with the first paragraph used as the meta description and links opening in a new tab, starting with the ORM category.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-26 19:42:22 +08:00
Vinta ChenandClaude c10264977e feat: serve redirect stubs for renamed and dissolved category slugs
Renamed or dissolved category slugs (e.g. /categories/web-servers/rpc/, /categories/code-analysis/code-linters/) returned 404, Search Console lists 7 of them, and each audit re-home was dropping the old URL's ranking.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-26 18:45:53 +08:00
Vinta ChenandClaude b7313dcffc test: assert bundled entries have a null PyPI override
The uv-audit bug had no automated guard: pypi_name_overrides.json is
a manual registry, so a wrong-package mapping is only caught if
someone already suspects it.

Two broader checks were measured against the real list and rejected.
Checking that PyPI metadata links back to the entry's GitHub repo
would not have caught uv-audit, since that package declares no
home_page or project_urls, landing it in a 26-entry bucket of
packages that simply don't declare a repo (numba, selenium, pyglet,
etc.), plus 10 benign cases of orgs moving or splitting bindings.
Flagging display-name/repo-name mismatches yields 46 hits, all
legitimate python-X-repo-to-X-package pairs, with uv-build sitting
among them despite being a real Astral package with the identical
shape to uv-audit.

What discriminates is the bundled marker itself: a "(part of X)"
entry ships inside something else and has no package of its own, so
the sweep must never query it. This test walks the real README and
requires a null override for every bundled entry whose normalized
name is PyPI-shaped. Verified it fails with exactly the uv-audit
message when that override is removed, and passes with it restored,
across the three current bundled entries with no false positives. It
runs offline, fitting the existing network-less CI.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-23 01:46:13 +08:00
Vinta ChenandClaude 0f677911f0 feat: add "Multiple on PyPI" badge for SDK monorepos
azure-sdk-for-python and google-cloud-python were rendering "Not on
PyPI", which is misleading. Both do ship on PyPI, just as many
per-service packages (azure-identity, azure-storage-blob,
google-cloud-storage, etc.) rather than under the repo name.

pypi_name_overrides.json already recorded that distinction in its
reason field; those two entries now carry an optional "badge" value
that build.py reads into the PyPI Downloads column. The other sixteen
no-count entries (cpython, renpy, agent skill repos, etc.) keep
"Not on PyPI" since that remains accurate for them.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-23 01:28:33 +08:00
Vinta ChenandClaude 733021ae5b feat: add Bundled badge for entries shipped inside a larger project
django.db.models, geodjango, httpx.URL and uv audit were rendering
"Not on PyPI" alongside eighteen genuinely standalone projects that
simply are not packaged on PyPI, conflating two different reasons for
a missing download count.

These four entries now carry a "(part of X)" description prefix in
README.md, mirroring the existing "(Python standard library)"
convention. build.py reads that prefix into a bundled flag that both
templates render as a "Bundled" badge.

The prefix approach was chosen over a separate data file so README.md
stays the single source of content truth, and over inferring from the
entry name because geodjango is neither dotted nor spaced and would
have been missed. Redundant tail wording was trimmed from the
httpx.URL, geodjango and uv audit descriptions now that the prefix
names the parent.

The new entry format is documented in CONTRIBUTING.md and the
vocabulary in CONTEXT.md.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-23 01:09:20 +08:00
Vinta ChenandClaude 2fc0edd565 feat: rename Built-in source type to Stdlib and show it in downloads column
Standard-library entries rendered "Not on PyPI" in the PyPI Downloads
column, which read like missing data rather than a deliberate category
— the build already forces downloads to None for them so they never
pick up a same-named PyPI backport. They now render a "Stdlib" badge
instead, while genuine non-PyPI entries keep "Not on PyPI".

The filter tag is renamed to match, so the source-type value, the row
filter tag, and the synthetic category heading all read Stdlib now.
The literal "Built-in" strings scattered through build.py are routed
through the existing BUILTIN_FILTER constant so the label lives in one
place. The category page slug stays "built-in" so the public URL
/categories/built-in/ does not break.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-23 01:01:17 +08:00
Vinta Chen ee8089d0d5 add build date to llms.txt 2026-08-16 20:16:05 +08:00
Vinta ChenandClaude 30c9f18bc2 feat: annotate llms.txt entries with PyPI download counts
Entries now end with "(PyPI downloads/month: N, GitHub stars: M)" where
known, replacing the stars-only note, since download counts are the
list's stated primary evidence signal. annotate_entries_with_stars is
renamed to annotate_entries_with_stats and looks downloads up by the
first link's display name, skipping category-index bullets (which link
into the site itself) and Built-in entries (which would otherwise hit
same-named PyPI backports like logging or asyncio).

The intro now mirrors the README subtitle verbatim with the
project/category totals on their own line below, and the "opinionated
catalog" wording is gone since the shortlist ADR is literally titled
"shortlist, not a catalog".

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-16 19:43:52 +08:00
Vinta ChenandClaude d3fec1f7fa feat: default-sort the website table by downloads per month
Entries with a download count now sort first (descending), with
stars, then Built-in, then name as fallback tiers for entries that
lack a count. main.js mirrors this in its default activeSort, clean
URL check, and third-click reset target. Sorting by stars remains one
header click away.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-16 19:15:21 +08:00
Vinta ChenandClaude cc804b1de2 feat: add Downloads/Month column to website table
Sourced from website/data/pypi_downloads.tsv the same way
github_stars.json feeds the stars column. The new sortable column
sits between GitHub Stars and Last Commit on the homepage and
category pages, formatted with thousands separators like stars, with
an em dash when no PyPI data exists. Rows are matched by normalized
README display name; Built-in entries never show counts since
same-named PyPI packages are stdlib backports (e.g. the asyncio
package).

Below 960px the column hides and the count moves into the expand
row, mirroring the existing Last Commit treatment. main.js gains the
downloads sort branch and URL param.

The deploy workflow fetches the TSV via the new
make fetch_pypi_downloads target with a daily actions/cache
fallback, mirroring the stars fetch, but non-fatal: the column
degrades to dashes when the fetch fails, unlike stars which the
build requires.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-16 17:52:04 +08:00
Vinta Chen c0b80fd75f fix: surface sponsorship link in header 2026-06-07 03:22:28 +08:00
Vinta Chen 32ae78fd96 fix: improve website SEO metadata 2026-06-07 03:08:43 +08:00
Vinta Chen 10c06fb26d add category links in llms.txt 2026-05-07 20:00:56 +08:00
Vinta Chen 6c18b6447e feat: use explicit Projects section in README 2026-05-04 21:24:57 +08:00
Vinta Chen 921d47b455 remove index.md 2026-05-04 17:11:34 +08:00
Vinta Chen 3510db9df9 update llms.txt 2026-05-04 17:05:05 +08:00
Vinta Chen 509ebaff7a use file modification time as lastmod in sitemap 2026-05-04 16:24:52 +08:00
Vinta ChenandClaude 28b61a9212 style(seo): switch category page title separator from pipe to hyphen
Google truncates pipe separators and treats hyphens as cleaner word
boundaries in SERP titles.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-03 20:03:29 +08:00
Vinta ChenandClaude c886e470b6 feat(website): lead category meta description with real description when present, count first as fallback
Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-03 19:57:31 +08:00