Skip to content

Conversation

@arnaucasau
Copy link
Collaborator

@arnaucasau arnaucasau commented Jan 14, 2026

Summary

This PR moves the metadata of every Jupyter notebook to the frontmatter at the top of their first markdown cell. It also tweaks our markdown check to understand the new format.

To migrate all the files, I used the following script that can be used from the scripts/js/commands folder:

Script
import { has } from "lodash-es";
import { globby } from "globby";

import { readJsonFile } from "../lib/fs";
import { writeFile } from "fs/promises";
import { zxMain } from "../lib/zx";

const KEYS_TO_MIGRATE = ["title", "description"];

zxMain(async () => {
  const allNotebookPaths = await globby(["{docs,learning}/**/*.ipynb"]);

  for (const notebookPath of allNotebookPaths) {
    const nb = await readJsonFile(notebookPath);

    if (!nb.metadata.title || !nb.metadata.description) return;

    const meta = ["---\n"];
    for (const key of KEYS_TO_MIGRATE) {
      if (has(nb.metadata, key)) {
        if (nb.metadata[key].includes(":")) {
          nb.metadata[key] = `"${nb.metadata[key]}"`;
        }

        meta.push(`${key}: ${nb.metadata[key]}\n`);
        delete nb.metadata[key];
      }
    }
    meta.push("---\n");
    meta.push("\n");
    meta.push("\n");

    const firstMdCell = nb.cells.find(
      (cell: any) => cell.cell_type === "markdown",
    );
    firstMdCell.source = [...meta, ...firstMdCell.source];

    await writeFile(notebookPath, JSON.stringify(nb, null, 1) + "\n");
  }
});

Commits

  • d3a528e: Updates the metadata check to support the new format. You can see an example of the checker detecting issues in this job
  • 09701e1: Migrates all the notebook's metadata by using the script mentioned above
  • e48b121: Fixes spelling typos that weren't previously detected.
  • fa63db7: Fixes how we got the metadata title in a CI check
  • 92d909d: Removes the metadata Jupyter Notebook instructions from the MDX Guide.
  • 03f9a53: Updates the start script to include the support of the new notebook's metadata format.

@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

Comment on lines +41 to +43
first_md_cell = next((item for item in data['cells'] if item['cell_type'] == 'markdown'))
title_line = next((item for item in first_md_cell['source'] if item.startswith("title:")))
return title_line.split("title:", 1)[1].strip()
Copy link
Collaborator Author

@arnaucasau arnaucasau Jan 14, 2026

Choose a reason for hiding this comment

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

Given that this in a CI check, this code assumes that we already validated that every notebook has the metadata at the top of the first markdown cell. We could validate every assumption here to make it fully independent, but I wasn't sure if it was overkill. We could do:

def get_notebook_title(path: Path) -> str:
    data = json.loads(path.read_text())
    try:
        first_md_cell = next((item for item in data['cells'] if item['cell_type'] == 'markdown'))
    except StopIteration:
        raise Exception("Make sure your notebook defined the metadata in a markdown cell!")

    if first_md_cell['source'][0] != '---\n':
        raise Exception("The metadata must be defined at the top of the first markdown cell!")

    try:
        title_line = next((item for item in first_md_cell['source'] if item.startswith("title:")))
    except StopIteration:
        raise Exception("Make sure your notebook has a 'title' metadata!")

    title_text = title_line.split("title:", 1)[1].strip()
    if not title_text:
        raise Exception("Make sure your notebook's 'title' is not empty.")

    return title_text

Alternatively, maybe just adding a comment is enough? Wdyt?

@arnaucasau arnaucasau marked this pull request as ready for review January 14, 2026 11:53
@arnaucasau arnaucasau changed the title [WIP] Move metadata for Jupyter Notebooks to frontmatter Move metadata for Jupyter Notebooks to frontmatter Jan 14, 2026
@qiskit-bot
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants