Before a {listing} can display anything, it has to collect its items.
The :source: option picks a collector, which produces a list of items (defined below).
These collectors are built in, and other plugins can add more (see Extending):
Source | Collects from |
|
|---|---|---|
| Markdown files on disk, using their frontmatter | a glob, e.g. |
| The pages under one page in | the parent page, e.g. |
| A YAML file whose top-level entries are items | a |
| A JSON file whose top-level array entries are items | a |
| A TOML file whose array-of-tables entries are items | a |
| A CSV or TSV file whose header row names the fields and whose other rows are items | a |
A relative :path: resolves from the page containing the directive, like a Markdown link.
Items¶
An item is a plain object: a collector produces a list of them, and a display renders them. No field is required, but the built-in displays and options understand these:
Field | Used for |
|---|---|
| The item’s name, linked to |
| Where the item links to. |
| Summary text. Displays that show page content fall back to it when an item has no |
| The default sort key ( |
| A single name or a list, shown beside the date. Names are shown as written (an id referencing a project author is not resolved). |
| A list of strings, shown as a tag row (see |
| Image URL for displays that show images. |
| The page’s parsed content, set by the |
Any other fields pass through untouched; use them as :columns: or :filter: targets.
files¶
The default. Point :path: at a glob of Markdown files; each file’s frontmatter becomes an item, and its URL links to the built page.
Most examples in the displays pages use this source.
toc¶
Set :source: toc to list the pages nested under a page in your myst.yml table of contents, in the same order.
By default it lists the children of the page holding the listing; point :path: at another page to list its children instead.
Pair it with the list display for a table of contents that shows each page’s description:
:::{listing}
:source: toc
:path: displays/index.md
:display: list
:::- Table display: Rows and columns of the fields you pick.
- List display: One bullet per item, with a few fields on the same line.
- Gallery display: A grid of image-forward cards.
- Summary display: Stacked cards that show each description.
- Feed display: The full body of each item, stacked for reading.
- Sections display: Each item as a real section in the page outline.
Each item is the page’s frontmatter, so :columns: can show any field it has.
The first column is the link text, so short_title gives shorter links (pages without one fall back to title):
:::{listing}
:source: toc
:path: displays/index.md
:display: list
:columns: short_title,description
:::- Table: Rows and columns of the fields you pick.
- List: One bullet per item, with a few fields on the same line.
- Gallery: A grid of image-forward cards.
- Summary: Stacked cards that show each description.
- Feed: The full body of each item, stacked for reading.
- Sections: Each item as a real section in the page outline.
The first page in the toc is the site’s root page, so its children are the other top-level entries. This lists the top level of this site from any page:
:::{listing}
:source: toc
:path: index.md
:display: list
:::- Get started: Install the plugin and render your first listing.
- Tutorial: Build listings from your pages, a data file, and data written in the directive.
- Collectors
- Transform
- Displays
- Develop: Change this plugin, or build your own collectors and displays on top of it.
- Releases
Items come in toc order, so they aren’t sorted or limited unless you set :sort: or :limit:.
A few things to know:
Only direct children are listed, not grandchildren.
A
urlentry becomes an external link, and atitlewith nofilebecomes an unlinked item.hiddenentries are skipped.A notebook’s fields come from the frontmatter in its first cell.
Your
myst.ymlneeds an explicittoc;extends:and_toc.ymlaren’t read.fileentries need their extension (guides/intro.md, notguides/intro), as mystmd itself recommends.
yaml¶
Set :source: yaml and point :path: at a .yml file whose top-level entries use the item fields:
:::{listing}
:source: yaml
:path: links.yml
:columns: title,description,date
:::| Title | Description | Date |
|---|---|---|
| Jupyter Book | Build publication-quality books and documents from computational material, combining prose, code, and live outputs in a single project. | January 15, 2025 |
| Project Jupyter | The open-source project behind notebooks, JupyterLab, and the broader interactive computing ecosystem used across science and education. | September 10, 2024 |
| MyST Markdown | The MyST document engine — a fast, extensible toolchain for technical writing that turns Markdown and notebooks into books, articles, and websites. | June 1, 2024 |
| Executable Books | The community that grew the original Jupyter Book and MyST, dedicated to open tools for reproducible, computational narratives. | March 22, 2024 |
| Wide thumbnail (3:1) | A landscape image, cropped at top and bottom to fit the 3:2 cover. | |
| Tall thumbnail (1:2) | A portrait image, cropped at the sides to fit the 3:2 cover. | |
| Square thumbnail (1:1) | A square image, lightly cropped to fit the 3:2 cover. |
For a short, one-off listing, write the YAML list in the directive body instead.
The body wins over :path: when both are given.
:::{listing}
:source: yaml
:columns: title,description
- title: Inline One
description: Written in the directive body
- title: Inline Two
description: No file needed
:::| Title | Description |
|---|---|
| Inline One | Written in the directive body |
| Inline Two | No file needed |
json¶
Like yaml, but for JSON: point :path: at a .json file holding one top-level array, or write the array inline in the directive body.
JSON is most useful when another tool writes the data for you.
For example, gh can dump GitHub issues into a listing-ready file:
gh issue list --limit 5 --json title,url,updatedAt > issues.jsonThis site’s issues.json came from that command, so the table below shows this repo’s open issues:
:::{listing}
:source: json
:path: issues.json
:columns: title,updatedAt
:sort: updatedAt-desc
:::| Title | UpdatedAt |
|---|---|
| Add a JSON collector | August 11, 2026 |
| Allow users to dynamically sort tables | July 28, 2026 |
| Add column or entry option for something like "completion amount" | July 24, 2026 |
| Allow for hierarchical or nested listings like a list-mode | July 11, 2026 |
| Consider an array for the `sort` option? | July 3, 2026 |
toml¶
Like yaml, but for TOML.
TOML has no top-level list, so wrap the items in a single array-of-tables.
The key’s name is up to you; here it’s items:
:::{listing}
:source: toml
:columns: title,description
[[items]]
title = "Toml One"
description = "Written in the directive body"
[[items]]
title = "Toml Two"
description = "No file needed"
:::| Title | Description |
|---|---|
| Toml One | Written in the directive body |
| Toml Two | No file needed |
A .toml file works the same way:
:::{listing}
:source: toml
:path: links.toml
:columns: title,description,date
:::| Title | Description | Date |
|---|---|---|
| Jupyter Book | Publication-quality books from computational material. | January 15, 2025 |
| MyST Markdown | The MyST document engine for technical writing. | June 1, 2024 |
csv and tsv¶
Set :source: csv and point :path: at a .csv file.
The header row names the item fields, and each row after it is one item.
Separate several tags in one cell with ;:
:::{listing}
:source: csv
:path: links.csv
:columns: title,description,tags
:::| Title | Description | Tags |
|---|---|---|
| Jupyter Book | Build books and documents from computational material, like notebooks | docs |
| MyST Markdown | The MyST document engine | docs; tools |
Like the other data sources, you can write the CSV in the directive body instead:
:::{listing}
:source: csv
:columns: title,description
title,description
Csv One,Written in the directive body
Csv Two,"Quoted, so it can hold a comma"
:::| Title | Description |
|---|---|
| Csv One | Written in the directive body |
| Csv Two | Quoted, so it can hold a comma |
Every value is a string, so a numeric column sorts as text.
For a tab-separated file, use :source: tsv:
:::{listing}
:source: tsv
:path: links.tsv
:columns: title,description
:::| Title | Description |
|---|---|
| Jupyter Book | Build books, articles, and websites from notebooks |
| MyST Markdown | The MyST document engine |
Unknown sources¶
An unknown :source: warns and renders a note:
:::{listing}
:source: nope
:::