From 7974eeacdf5412dd8fe58bbe533efab61dbd1a0f Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Mon, 26 Oct 2026 10:46:44 +0800 Subject: [PATCH 1/9] fix: render group page category list as collapsible details Group pages rendered "Browse by category" with a plain div heading instead of the homepage's details/summary, so the two-column grid never applied, the arrow showed but did nothing, and the list didn't collapse on phones. Co-Authored-By: Claude --- website/templates/category.html | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/website/templates/category.html b/website/templates/category.html index 4399505c..c1a49186 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -56,18 +56,26 @@ {% if group_categories %} {% endif %} From a7df2a9f0ef2953be0e9e423bd6c6099fee9aa22 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Mon, 26 Oct 2026 10:49:11 +0800 Subject: [PATCH 2/9] refactor: share the hero category nav between home and category pages The "Browse by category" markup was duplicated in index.html and category.html, and the two copies had drifted. Co-Authored-By: Claude --- website/templates/_category_nav.html | 22 ++++++++++++++++++++++ website/templates/category.html | 23 +---------------------- website/templates/index.html | 23 +---------------------- 3 files changed, 24 insertions(+), 44 deletions(-) create mode 100644 website/templates/_category_nav.html diff --git a/website/templates/_category_nav.html b/website/templates/_category_nav.html new file mode 100644 index 00000000..c6f60bd6 --- /dev/null +++ b/website/templates/_category_nav.html @@ -0,0 +1,22 @@ + diff --git a/website/templates/category.html b/website/templates/category.html index c1a49186..b64af1a3 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -55,28 +55,7 @@ {% if group_categories %} - + {%+ with nav_categories = group_categories %}{% include "_category_nav.html" %}{% endwith +%} {% endif %} diff --git a/website/templates/index.html b/website/templates/index.html index fcea908b..af081acb 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -50,28 +50,7 @@ - + {%+ with nav_categories = categories %}{% include "_category_nav.html" %}{% endwith +%} {% endblock %} From f02791ac58af33d5306dceef8087de6ba63b305b Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Mon, 26 Oct 2026 10:53:55 +0800 Subject: [PATCH 3/9] refactor: extract the Contribute CTA into a shared partial Co-Authored-By: Claude --- website/templates/_final_cta.html | 23 +++++++++++++++++++++++ website/templates/category.html | 24 +----------------------- website/templates/index.html | 24 +----------------------- 3 files changed, 25 insertions(+), 46 deletions(-) create mode 100644 website/templates/_final_cta.html diff --git a/website/templates/_final_cta.html b/website/templates/_final_cta.html new file mode 100644 index 00000000..95c7c58b --- /dev/null +++ b/website/templates/_final_cta.html @@ -0,0 +1,23 @@ +
+
+ +

Know a project that belongs here?

+

Tell us what it does and why it stands out.

+ +
+
diff --git a/website/templates/category.html b/website/templates/category.html index b64af1a3..cdadd21f 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -324,27 +324,5 @@ {% endif %} -
-
- -

Know a project that belongs here?

-

Tell us what it does and why it stands out.

- -
-
+{% include "_final_cta.html" +%} {% endblock %} diff --git a/website/templates/index.html b/website/templates/index.html index af081acb..b6b1e578 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -266,27 +266,5 @@ -
-
- -

Know a project that belongs here?

-

Tell us what it does and why it stands out.

- -
-
+{% include "_final_cta.html" +%} {% endblock %} From f4191b274619a75f9d550ce2a899f0a87e8a3cc4 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Mon, 26 Oct 2026 10:55:51 +0800 Subject: [PATCH 4/9] refactor: extract shared projects table macro Co-Authored-By: Claude --- website/templates/_projects_table.html | 74 ++++++++++++++++++++++++++ website/templates/category.html | 74 ++------------------------ website/templates/index.html | 74 ++------------------------ 3 files changed, 80 insertions(+), 142 deletions(-) create mode 100644 website/templates/_projects_table.html diff --git a/website/templates/_projects_table.html b/website/templates/_projects_table.html new file mode 100644 index 00000000..193000e3 --- /dev/null +++ b/website/templates/_projects_table.html @@ -0,0 +1,74 @@ +{% macro projects_table(count, scope, editorial=false) %} +
+

Search and filter

+
+ + +
+
+ +

Results

+
+ + + + + + + + + + + + + +{{ caller() }} + +
Row number + + + + + + + + Tags + +
+
+ + +{% endmacro %} diff --git a/website/templates/category.html b/website/templates/category.html index cdadd21f..10fa0bd5 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% from "_projects_table.html" import projects_table %} {% block title %}{{ category_title }}{% endblock %} {% block description %}{{ category_description }}{% endblock %} {% block canonical_url %}{{ category_url }}{% endblock %} @@ -216,66 +217,7 @@

-
-

Search and filter

-
- - -
-
- -

Results

-
- - - - - - - - - - - - - + {% call projects_table(entries | length, "in " ~ category.name, entry_groups) %} {% if entry_groups %} {% set row = namespace(index=0) %} {% for group in entry_groups %} @@ -302,17 +244,7 @@ {{ entry_rows(entry, loop.index) }} {% endfor %} {% endif %} - -
Row number - - - - - - - - Tags - -
-
- - + {% endcall %} {% if guide_html %} diff --git a/website/templates/index.html b/website/templates/index.html index b6b1e578..8d0a4385 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% from "_projects_table.html" import projects_table %} {% block extra_head %} {% endblock %} @@ -68,66 +69,7 @@

-
-

Search and filter

-
- - -
-
- -

Results

-
- - - - - - - - - - - - - + {% call projects_table(entries | length, "across " ~ total_categories ~ " categories") %} {% for entry in entries %} {% endfor %} - -
Row number - - - - - - - - Tags - -
-
- - + {% endcall %} {% include "_final_cta.html" +%} From aa6f632ed835deb905056d65511b4353454384c0 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Mon, 26 Oct 2026 10:57:03 +0800 Subject: [PATCH 5/9] refactor: share entry rows macro between home and category pages Co-Authored-By: Claude --- website/templates/_entry_rows.html | 133 ++++++++++++++++++++++++++++ website/templates/category.html | 134 +---------------------------- website/templates/index.html | 125 +-------------------------- 3 files changed, 136 insertions(+), 256 deletions(-) create mode 100644 website/templates/_entry_rows.html diff --git a/website/templates/_entry_rows.html b/website/templates/_entry_rows.html new file mode 100644 index 00000000..5629aff2 --- /dev/null +++ b/website/templates/_entry_rows.html @@ -0,0 +1,133 @@ +{% macro entry_rows(entry, index, home=false) %} + {# On section and subcategory pages the group heading already names the row's use case #} + {% set grouped_page = entry_groups and not group_categories %} + {% set section_path = "/categories/" ~ parent_category.slug ~ "/" if parent_category else current_path %} + + {{ index }} + + {{ entry.name }} + {% if entry.subcategories %}{{ entry.subcategories[0].name }}{% + else %}{{ entry.categories[0] if home else category.name }}{% endif %} + + + {% if entry.downloads is not none %}{{ + "{:,}".format(entry.downloads) }}{% elif entry.source_type == + 'Stdlib' %}Stdlib{% elif + entry.bundled %}Bundled{% elif + entry.badge %}{{ entry.badge }}{% + else %}Not on PyPI{% endif %} + + + {% if entry.stars is not none %}{{ "{:,}".format(entry.stars) }}{% + elif entry.source_type %}{{ entry.source_type }}{% else %}—{% endif %} + + + {% if entry.last_commit_at %}{% else %}—{% endif %} + + + {% for subcat in entry.subcategories %} + + {{ subcat.name }} + + {% endfor %} + {% for cat in entry.categories %} + {{ cat }} + {% endfor %} + {% if entry.groups %} + {% set group_url = filter_urls[entry.groups[0]] %} + + {{ entry.groups[0] }} + + {% endif %} + {% if entry.source_type == 'Stdlib' %} + + Stdlib + + {% endif %} + + + + {% if entry.description %} + + + +
{{ entry.description | safe }}
+ + + {% endif %} + + + +
+ {% if entry.also_see %} +
+ Also see: {% for see in entry.also_see %}{{ see.name }}{% if not loop.last %}, {% endif %}{% endfor %} +
+ {% endif %} +
+ {% if entry.owner %}{{ entry.owner }}/{% endif %}{{ entry.url | replace("https://", "") }} + {% if entry.stars is not none %}/{{ + "{:,}".format(entry.stars) }} stars{% endif %} {% if entry.last_commit_at %}/{% endif %} +
+
+ + + +{% endmacro %} diff --git a/website/templates/category.html b/website/templates/category.html index 10fa0bd5..80f3753a 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -1,5 +1,6 @@ {% extends "base.html" %} {% from "_projects_table.html" import projects_table %} +{% from "_entry_rows.html" import entry_rows with context %} {% block title %}{{ category_title }}{% endblock %} {% block description %}{{ category_description }}{% endblock %} {% block canonical_url %}{{ category_url }}{% endblock %} @@ -62,139 +63,6 @@ {% endblock %} {% block content %} -{% macro entry_rows(entry, index) %} - {# On section and subcategory pages the group heading already names the row's use case #} - {% set grouped_page = entry_groups and not group_categories %} - {% set section_path = "/categories/" ~ parent_category.slug ~ "/" if parent_category else current_path %} - - {{ index }} - - {{ entry.name }} - {% if entry.subcategories %}{{ entry.subcategories[0].name }}{% - else %}{{ category.name }}{% endif %} - - - {% if entry.downloads is not none %}{{ - "{:,}".format(entry.downloads) }}{% elif entry.source_type == - 'Stdlib' %}Stdlib{% elif - entry.bundled %}Bundled{% elif - entry.badge %}{{ entry.badge }}{% - else %}Not on PyPI{% endif %} - - - {% if entry.stars is not none %}{{ "{:,}".format(entry.stars) }}{% - elif entry.source_type %}{{ entry.source_type }}{% else %}—{% endif %} - - - {% if entry.last_commit_at %}{% else %}—{% endif %} - - - {% for subcat in entry.subcategories %} - - {{ subcat.name }} - - {% endfor %} - {% for cat in entry.categories %} - {{ cat }} - {% endfor %} - {% if entry.groups %} - {% set group_url = filter_urls[entry.groups[0]] %} - - {{ entry.groups[0] }} - - {% endif %} - {% if entry.source_type == 'Stdlib' %} - - Stdlib - - {% endif %} - - - - {% if entry.description %} - - - -
{{ entry.description | safe }}
- - - {% endif %} - - - -
- {% if entry.also_see %} -
- Also see: {% for see in entry.also_see %}{{ see.name }}{% if not loop.last %}, {% endif %}{% endfor %} -
- {% endif %} -
- {% if entry.owner %}{{ entry.owner }}/{% endif %}{{ entry.url | replace("https://", "") }} - {% if entry.stars is not none %}/{{ - "{:,}".format(entry.stars) }} stars{% endif %} {% if entry.last_commit_at %}/{% endif %} -
-
- - - -{% endmacro %} {% include "_sponsor_band.html" %}
diff --git a/website/templates/index.html b/website/templates/index.html index 8d0a4385..35a8235a 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -1,5 +1,6 @@ {% extends "base.html" %} {% from "_projects_table.html" import projects_table %} +{% from "_entry_rows.html" import entry_rows with context %} {% block extra_head %} {% endblock %} @@ -71,129 +72,7 @@ {% call projects_table(entries | length, "across " ~ total_categories ~ " categories") %} {% for entry in entries %} - - {{ loop.index }} - - {{ entry.name }} - {% if entry.subcategories %}{{ entry.subcategories[0].name }}{% - else %}{{ entry.categories[0] }}{% endif %} - - - {% if entry.downloads is not none %}{{ - "{:,}".format(entry.downloads) }}{% elif entry.source_type == - 'Stdlib' %}Stdlib{% elif - entry.bundled %}Bundled{% elif - entry.badge %}{{ entry.badge }}{% - else %}Not on PyPI{% endif %} - - - {% if entry.stars is not none %}{{ "{:,}".format(entry.stars) }}{% - elif entry.source_type %}{{ entry.source_type }}{% else %}—{% endif %} - - - {% if entry.last_commit_at %}{% else %}—{% endif %} - - - {% for subcat in entry.subcategories %} - - {{ subcat.name }} - - {% endfor %} {% for cat in entry.categories %} - {{ cat }} - {% endfor %} - - {{ entry.groups[0] }} - - {% if entry.source_type == 'Stdlib' %} - - Stdlib - - {% endif %} - - - - {% if entry.description %} - - - -
{{ entry.description | safe }}
- - - {% endif %} - - - -
- {% if entry.also_see %} -
- Also see: {% for see in entry.also_see %}{{ see.name }}{% if not loop.last %}, {% endif %}{% endfor %} -
- {% endif %} -
- {% if entry.owner %}{{ entry.owner }}/{% endif %}{{ entry.url | replace("https://", "") }} - {% if entry.stars is not none %}/{{ - "{:,}".format(entry.stars) }} stars{% endif %} {% if entry.last_commit_at %}/{% endif %} -
-
- - - + {{ entry_rows(entry, loop.index, home=true) }} {% endfor %} {% endcall %}
From a1e6058986ecc2d852adbe0755385900998fd422 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Mon, 26 Oct 2026 10:57:55 +0800 Subject: [PATCH 6/9] refactor: extract site topbar into a shared template partial Co-Authored-By: Claude --- website/templates/_topbar.html | 20 ++++++++++++++++++++ website/templates/category.html | 15 +-------------- website/templates/index.html | 14 +------------- website/templates/sponsorship.html | 14 +------------- 4 files changed, 23 insertions(+), 40 deletions(-) create mode 100644 website/templates/_topbar.html diff --git a/website/templates/_topbar.html b/website/templates/_topbar.html new file mode 100644 index 00000000..0fcde817 --- /dev/null +++ b/website/templates/_topbar.html @@ -0,0 +1,20 @@ + diff --git a/website/templates/category.html b/website/templates/category.html index 80f3753a..4ec943e8 100644 --- a/website/templates/category.html +++ b/website/templates/category.html @@ -13,20 +13,7 @@
- + {%+ with all_projects = true %}{% include "_topbar.html" %}{% endwith +%}
{% if parent_category %} diff --git a/website/templates/index.html b/website/templates/index.html index 35a8235a..165e77d3 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -9,19 +9,7 @@
- + {%+ with home = true %}{% include "_topbar.html" %}{% endwith +%}
diff --git a/website/templates/sponsorship.html b/website/templates/sponsorship.html index 72c5bc2d..cafbfda1 100644 --- a/website/templates/sponsorship.html +++ b/website/templates/sponsorship.html @@ -11,19 +11,7 @@
- + {%+ include "_topbar.html" +%}

Sponsorship

From f5ec5dd79618e283a9ae456ad6a6d96424b20c59 Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Mon, 26 Oct 2026 11:01:56 +0800 Subject: [PATCH 7/9] style: hide group project count on phones On phones (max-width 680px) the "N projects" count beside each group heading on category pages crowded the heading into a narrow column. Co-Authored-By: Claude --- website/static/style.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/static/style.css b/website/static/style.css index 12c86ba4..2b94f8a5 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1905,7 +1905,8 @@ th[data-sort].sort-asc::after { } .col-num, - .col-cat { + .col-cat, + .group-count { display: none; } From 0b9e69252d855c7ef502e7aba529ef88a19440bf Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Mon, 26 Oct 2026 11:10:13 +0800 Subject: [PATCH 8/9] style: right-align row arrow on phones On phones the row arrow was centered in its column, leaving a wider gap on the right edge than on the left. Co-Authored-By: Claude --- website/static/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/website/static/style.css b/website/static/style.css index 2b94f8a5..75b0de84 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1948,6 +1948,7 @@ th[data-sort].sort-asc::after { .col-arrow { width: 1.8rem; + text-align: right; } } From be3956f90291da84bbdbaf72fa2fd6a723c854fa Mon Sep 17 00:00:00 2001 From: Vinta Chen Date: Mon, 26 Oct 2026 11:11:04 +0800 Subject: [PATCH 9/9] style: hide back-to-top label on phones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On phones the "Top ↑" header button was wider than the row arrows, so it set the arrow column's width and left a wide gap between the downloads number and the arrow. Co-Authored-By: Claude --- website/static/style.css | 4 +++- website/templates/_projects_table.html | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/website/static/style.css b/website/static/style.css index 75b0de84..f8eca400 100644 --- a/website/static/style.css +++ b/website/static/style.css @@ -1906,7 +1906,9 @@ th[data-sort].sort-asc::after { .col-num, .col-cat, - .group-count { + .group-count, + /* Leaves the arrow column as narrow as the row arrows */ + .back-to-top-label { display: none; } diff --git a/website/templates/_projects_table.html b/website/templates/_projects_table.html index 193000e3..0152e5ec 100644 --- a/website/templates/_projects_table.html +++ b/website/templates/_projects_table.html @@ -53,7 +53,7 @@ Tags