Follow-up to #3103. Expands the SEO/AEO discovery surface and reworks how filtering works on awesome-python.com.
Static category pages under /categories/ for every group, category, and subcategory, with breadcrumbs and inclusion in the sitemap. Category pages mirror the index layout (expand rows, descriptions, results note) so any landing surface feels consistent.
Path-based filter URLs replace the old querystring scheme. The index embeds a filter-to-url map (with </script> escaped) so tag clicks route client-side without losing crawlable URLs.
Homepage category directory with slugs/URLs, plus a "Browse by category" nav on group pages.
/sponsorship/ landing page describing tiers and editorial-independence policy.
Tooling: make lint, make format, make typecheck targets, ty added for type checking, ruff format applied, build template entries typed.
Misc: rename group Miscellaneous → Other; remove duplicate tag rendering on group/category pages.
Test plan
make test (117 passed)
make build (14 groups, 71 categories, 537 entries)
Spot-check /categories/<group>/, /categories/<group>/<category>/, and /categories/built-in/ render and link correctly
Confirm tag clicks on the index update the URL via the path-based map and Back button works
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/vinta/awesome-python/pull/3106
Author: @vinta
Created: 5/3/2026
Status: ✅ Merged
Merged: 5/3/2026
Merged by: @vinta
Base:
master← Head:feature/better-seo-2📝 Commits (10+)
e11afd1feat(website): generate static category pagesc98cbe2style(website): clarify category section headingb00395aadd missing links of category descriptions7fadbaffeat(website): add homepage category directory4005c2efeat(website): add slug and url to subcategory entries39d4b3dfeat(website): add subcategory_path and subcategory_public_url helpersa46b57efix(readme): rename group "Miscellaneous" to "Other"583d5e7feat(website): assert unique slugs across categories and groupscee1e65test(website): hoist pytest import to module level532d93dfeat(website): generate static pages for groups under /categories/📊 Changes
18 files changed (+1811 additions, -295 deletions)
View changed files
📝
DESIGN.md(+0 -0)📝
Makefile(+9 -0)📝
README.md(+2 -2)📝
SPONSORSHIP.md(+1 -1)📝
pyproject.toml(+22 -8)📝
uv.lock(+32 -2)📝
website/build.py(+228 -36)📝
website/fetch_github_stars.py(+1 -5)📝
website/readme_parser.py(+35 -26)📝
website/static/main.js(+70 -10)📝
website/static/style.css(+432 -1)📝
website/templates/base.html(+6 -3)➕
website/templates/category.html(+283 -0)📝
website/templates/index.html(+35 -12)➕
website/templates/sponsorship.html(+250 -0)📝
website/tests/test_build.py(+396 -115)📝
website/tests/test_fetch_github_stars.py(+2 -31)📝
website/tests/test_readme_parser.py(+7 -43)📄 Description
Summary
Follow-up to #3103. Expands the SEO/AEO discovery surface and reworks how filtering works on awesome-python.com.
/categories/for every group, category, and subcategory, with breadcrumbs and inclusion in the sitemap. Category pages mirror the index layout (expand rows, descriptions, results note) so any landing surface feels consistent.</script>escaped) so tag clicks route client-side without losing crawlable URLs./sponsorship/landing page describing tiers and editorial-independence policy.make lint,make format,make typechecktargets,tyadded for type checking, ruff format applied, build template entries typed.Miscellaneous→Other; remove duplicate tag rendering on group/category pages.Test plan
make test(117 passed)make build(14 groups, 71 categories, 537 entries)/categories/<group>/,/categories/<group>/<category>/, and/categories/built-in/render and link correctly/sponsorship/renders and nav works🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.