group_categories only ever appended a Resources group when the
resources list was non-empty. All call sites passed an empty list,
making it a no-op indirection. Inline parsed_groups directly and
remove the dead code along with its tests.
Co-Authored-By: Claude <noreply@anthropic.com>
Resources are no longer passed through parse_readme, group_categories,
or the index template — they are replaced with empty lists and the
unused variable is prefixed with an underscore.
Co-Authored-By: Claude <noreply@anthropic.com>
Within the same star count, built-in (stdlib) entries were interleaved
with third-party entries. Add a builtin tier to the sort key so stdlib
entries always rank below non-stdlib entries at equal star counts.
Co-Authored-By: Claude <noreply@anthropic.com>
Entries with source_type 'Built-in' have no extractable GitHub repo key
from their URL, so they never received star/metadata enrichment. Fall
back to python/cpython for these entries so the star count and related
data are populated correctly.
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, two entries sharing the same URL but different names would be
collapsed into one. Using a composite (url, name) key preserves distinct
entries while still merging true duplicates.
Co-Authored-By: Claude <noreply@anthropic.com>
Detect the hosting source (stdlib, GitLab, Bitbucket, External) from
the entry URL and surface it as a small badge in the stars column where
a star count would otherwise show an em dash.
Stdlib entries also get their own sort tier — between starred entries
and other no-star entries — so the standard library is not buried at
the bottom of each category.
Co-Authored-By: Claude <noreply@anthropic.com>
Entry was dead code with no callers. Switching from shutil.copy to
write_text uses the already-loaded readme_text variable directly instead
of re-reading the file from disk.
Co-Authored-By: Claude <noreply@anthropic.com>
The website builder previously relied on a hardcoded SECTION_GROUPS list in
build.py to organize categories into thematic groups. This was fragile: any
rename or addition to README.md required a matching code change.
Replace this with a parser-driven approach:
- readme_parser.py now detects bold-only paragraphs (**Group Name**) as
group boundary markers and groups H2 categories beneath them into
ParsedGroup structs.
- build.py drops SECTION_GROUPS entirely; group_categories() now just
passes parsed groups through and appends the Resources group.
- sort.py is removed as it relied on the old flat section model.
- Tests updated throughout to reflect the new (groups, resources) return
shape and to cover the new grouping logic.
Co-Authored-By: Claude <noreply@anthropic.com>
Entries appearing in more than one category were previously emitted as
separate rows. They are now deduplicated in build.py by URL, collecting
all category and group names into lists.
The template encodes those lists as pipe-delimited data attributes
(data-cats, data-groups) and renders a tag button per category.
The JS filter is updated to split on '||' and check for membership,
so clicking any category tag correctly shows the merged row.
Co-Authored-By: Claude <noreply@anthropic.com>
AI & ML: AI and Agents, Machine Learning, Deep Learning, Computer Vision,
Natural Language Processing, Recommender Systems, Robotics.
Data & Science: Data Analysis, Data Validation, Data Visualization,
Geolocation, Science, Quantum Computing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the Specialized catchall group. Redistribute its categories:
- Web & API: Admin Panels, CMS, Email, Static Site Generator, URL Manipulation
- AI & Data: Geolocation, Robotics
- Content & Media: Game Development, Internationalization
- System & Runtime: Date and Time, Hardware, Microsoft Windows
- Development Tools: Algorithms and Design Patterns
Only Miscellaneous remains ungrouped (falls into Other).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reformats dict and list literals to trailing-comma multiline style
throughout. Also copies README.md to llms.txt in the site output so
LLM crawlers can discover the full content.
Co-Authored-By: Claude <noreply@anthropic.com>
Switch readme_parser.py from regex-based parsing to markdown-it-py for
more robust and maintainable Markdown AST traversal. Update build pipeline,
templates, styles, and JS to support the new parser output. Refresh GitHub
stars data and update tests to match new parser behavior.
Co-Authored-By: Claude <noreply@anthropic.com>
Rename site_* targets to bare names (install, fetch_stats, build,
preview). Replace the static preview target with a watchmedo-driven
live-reload loop so file changes trigger automatic rebuilds. Make
the output directory creation idempotent (exist_ok=True) and static
copy incremental (dirs_exist_ok=True) so repeated builds don't wipe
output on each run.
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove `_has_description` which duplicated `_extract_description` logic;
use truthiness of the description string instead
- Remove unused `resources` parameter from `extract_entries`
- Merge two sequential loops in `parse_readme` into a single pass over
children to find hr, Resources, and Contributing indices
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
slugify, parse_readme, count_entries, extract_preview, render_content_html,
and related helpers are moved to a dedicated readme_parser module.
build.py now imports from readme_parser rather than defining these inline.
Tests for the removed functions are dropped from test_build.py since they
now live with the module they test.
Co-Authored-By: Claude <noreply@anthropic.com>
Replaces MkDocs with a bespoke Python site generator using Jinja2 templates
and Markdown. Adds uv for dependency management, GitHub Actions workflow for
deployment, and Makefile targets for local development (fetch_stars, build,
preview, deploy).
Co-Authored-By: Claude <noreply@anthropic.com>