How the gallery is built, and how to add your own cookbook to it.
The gallery is a thin collector for the
myst-listing
plugin: we fetch the cookbook metadata, myst-listing renders the cards, and
searchfilter
adds a live filter box.
The list of repositories to use in the gallery is in the cookbook_gallery.txt file.
Add a cookbook¶
Each card in the gallery is assembled from two files in each cookbook’s repo.
List the repo. Add its repository name (one per line) to
cookbook_gallery.txtat the root of this repo.Describe the card. Add a
_gallery_info.ymlto the root of your cookbook repo:thumbnail: thumbnail.png # path to an image in your repo tags: domains: [oceanography, climate] packages: [xarray, dask]
That’s it.
The card’s title comes from your cookbook’s myst.yml (project.title), and the description from your CITATION.cff abstract — so you don’t repeat them here.
What ends up on the card¶
| Card field | Source |
|---|---|
| Title | myst.yml → project.title |
| Description | CITATION.cff → abstract (or myst.yml project.description if set) |
| Thumbnail | _gallery_info.yml → thumbnail |
| Tags | _gallery_info.yml → tags (each category becomes a colored pill group) |
| Link | https://projectpythia.org/<repo-name> |
Each tag category (domains, packages, events) is passed through as its own
item field, and the listing’s :tag-fields: domains,packages,events renders each
as a separately-colored group of pills. Add a category to that list to show it.
How it works¶
{listing}(from myst-listing) with:source: pythiaemits alistingPlaceholdernode.Our document-stage transform in
src/pythia_gallery.pyfinds those nodes and fills each one’sitems— one entry per cookbook, fetched in parallel from the repos incookbook_gallery.txt.myst-listing renders the items as a gallery grid, and
{searchfilter}filters the cards client-side.
So src/pythia_gallery.py is only a collector: it never defines a directive or renders anything.
:source: pythia plugs straight into the standard {listing} directive and all its options, and myst-listing’s own collector ignores our source — so there’s no conflict.
The collected metadata is cached in docs/_build/pythia-gallery.json so rebuilds (including myst start’s hot reload) don’t re-fetch every repo. It refreshes when you edit cookbook_gallery.txt; delete docs/_build to force a full refresh. CI starts from a clean _build, so deploys always fetch fresh.
{searchfilter} targets .myst-listing-gallery .myst-card (not .myst-listing-item) because the gallery’s card nodes drop custom classes.
Preview locally¶
The whole site lives in docs/. Live-preview it with hot reload:
nox -s docs-live # serves the gallery + these docs at http://localhost:3000nox -s docs-live just runs myst start inside docs/, so you need myst on
your PATH (npm install -g mystmd, or the project conda env). No nox session?
cd docs && myst start does the same thing.
The plugins¶
docs/myst.yml loads both plugins from their GitHub releases — single built
bundles, no local checkout or build step:
- https://github.com/myst-contrib/myst-listing/releases/latest/download/plugin.mjs
- https://raw.githubusercontent.com/jupyter-book/myst-plugins/main/plugins/searchfilter/searchfilter.mjsmyst-listing tracks its newest release via latest/download; pin a specific
version by swapping that for a tag, e.g. download/v0.1.0. Because both are
fetched from URLs, the site builds anywhere — CI and fresh clones included.