Skip to content

Redesign the ecosystem package registry as a filterable card grid - #254

Open
Zethson wants to merge 7 commits into
mainfrom
redesign-ecosystem-registry
Open

Redesign the ecosystem package registry as a filterable card grid#254
Zethson wants to merge 7 commits into
mainfrom
redesign-ecosystem-registry

Conversation

@Zethson

@Zethson Zethson commented Aug 11, 2026

Copy link
Copy Markdown
Member

The ecosystem registry on /packages/#ecosystem was a two-column table of name and description, which ignored most of what the registry actually carries. This turns it into a searchable card grid.

Cards

Logo (or a monogram tile), version, license, description, tags, and a link row built from the registry fields: repository, docs, tutorials, PyPI / conda / CRAN / Bioconductor, and the first publication DOI. Packages in the core-* categories get a CORE badge; non-Python packages get a language badge.

Filtering

Free-text search over name, description, tags, category and language, plus a chip row of the primary categories in use, biggest first. Tags filter from the cards themselves — there are 45 of them, too many for a chip row. Both vocabularies are controlled by the registry schema, so this template does no normalisation: no alias map, no frequency threshold, no top-N slice.

Depends on scverse/ecosystem-packages#392

That PR adds primary_category, the controlled tags enum and language. It needs to merge and redeploy before this one — until then the live packages.json has no primary_category and the chip row renders empty (the grid and search still work).

Closes #106.

Also in here

  • Netlify deploy previews were building with Hugo 0.97.2 from 2022 while production uses latest. netlify.toml pins them to 0.164.0.
  • The search compiled user input into a RegExp, so typing ( threw and froze the filter. It now matches substrings against a prebuilt per-card index.
  • Duplicate outbound links are collapsed; many entries point documentation_home and tutorials_home at the same URL.

The registry was a two-column table of name and description, which
ignored most of what packages.json actually carries.

Each package is now a card showing its logo (or a monogram tile),
version, license, description, tags, and a link row built from the
registry data: repository, docs, tutorials, PyPI/conda/CRAN/Bioconductor
and the first publication DOI. Entries in the core-* categories get a
badge so they are distinguishable from community submissions.

Filtering is search over name, description and tags plus a row of the
twelve most common tags. Registry tags are free-form, so variants such
as "single-cell", "single cell" and "singlecell" are folded together
through an alias map before they are counted. Tags on a card filter by
that tag as well, injecting a chip when it is not one of the top twelve.

Along the way:

- Wrap the remote fetch in `try`, so a registry outage degrades to a
  link instead of failing the build.
- Match the search query as a substring instead of compiling user input
  into a RegExp, which threw on input such as `(`.
- Collapse duplicate outbound links; many entries point
  documentation_home and tutorials_home at the same URL.
- Drop the <p> wrapping markdownify output, which nested paragraphs.
@netlify

netlify Bot commented Aug 11, 2026

Copy link
Copy Markdown

Deploy Preview for jade-cajeta-1bcca0 ready!

Name Link
🔨 Latest commit 3b96ce4
🔍 Latest deploy log https://app.netlify.com/projects/jade-cajeta-1bcca0/deploys/6a7d80554c811e000855597f
😎 Deploy Preview https://deploy-preview-254--jade-cajeta-1bcca0.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Deploy previews built with Netlify's default Hugo 0.97.2, from 2022,
while production builds with `latest`, currently 0.164.0. Previews
therefore did not reflect what gets published, and the `try` guard
around the registry fetch failed to parse on the older version.

Pin previews to 0.164.0, and drop `try`, which needs Hugo 0.141+, in
favour of the plain nil check the template used before. The fallback
markup stays, so an unreachable registry still renders a link rather
than an empty section.
Now that deploy previews build with the same Hugo as production, the
template can use `try` again: an unreachable registry falls back to a
link instead of failing the build. Verified by pointing the fetch at a
404 and confirming the page still builds with the fallback markup.

Note the resulting minimum Hugo version in the README.
@flying-sheep

flying-sheep commented Aug 11, 2026

Copy link
Copy Markdown
Member

Previously a registry outage would have crashed the build on $remoteData.Content; now it degrades to a link to the GitHub repository

why would we want this?

this sounds like intentionally introducing a bug?

Wrapping the fetch in `try` traded a loud failure for a silent one: a
transient outage would have published the page with all 118 packages
replaced by a fallback line, on a green build, until whenever the next
deploy happened.

Failing the build keeps the last good page live, since the deploy step
in gh-pages.yml only runs after a successful build, and puts a red X in
front of someone who can act on it. Degrading gracefully is worth
revisiting on its own, backed by a committed snapshot of packages.json
so an outage means stale data rather than an empty section, but it does
not belong in a redesign.
@Zethson

Zethson commented Aug 11, 2026

Copy link
Copy Markdown
Member Author

@flying-sheep actually, I think you're right. I wouldn't call it a bug per se but it's probably worse than just failing which gives us more information and something to handle. I'll revert this part.

Comment thread layouts/packages/list.html Outdated
<td>{{ $lib.description | markdownify }}</td>
</tr>

{{/* Author-provided tags are free-form, so fold the obvious spelling variants together. */}}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe someone knows a smarter way to do this. We could also consider catching this at registry creation time with a vocabulary but then users would still need to know it...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could have a JSON schema with possible options and validate the free-form entries against it in CI when admitting a new entry. We use this validation technique with BCAI: https://github.com/biocontext-ai/registry/blob/main/mcp_schema.json

@flying-sheep flying-sheep Aug 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about we have

  1. an alias dictionary, folding unambiguously equivalent tags together (like you do here but centralized)

  2. an automated comment on PRs telling

    • people about potential misspellings: “tag ‘floob’ is new, but we have ‘flood’ so if you meant that pls fix”
    • us about new tags people are adding / misspellings the clanker doesn’t recognize

    (also using the dictionary so people don’t get confusing comments about aliases we already handle)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With scverse/ecosystem-packages#392 we can enforce topics that we can then reuse here. WDYT?

@Zethson Zethson Aug 11, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All right - I got 2 thumbs up. Thanks! Let's loop in @grst here who's most familiar with the ecosystem registry and might also have opinions.

Comment thread layouts/packages/list.html
scverse/ecosystem-packages#392 replaces free-form tags with a controlled
vocabulary, a primary category and a language, so the normalisation this
template was doing can go: the alias map, the tag counting, the `>= 3`
threshold and the top-12 slice are all deleted.

The chip row is now the categories actually in use, biggest first, which
is stable across registry updates rather than shifting whenever a
package is added. Tags filter from the cards, since 45 of them would not
fit in a chip row, and non-Python packages get a language badge.

Needs scverse/ecosystem-packages#392 merged and redeployed first. Until
then the live packages.json has no primary_category, and the chip row
renders empty.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Group ecosystem packages by category

4 participants