Skip to content

[Experimental] Use jupyter-book 2.0 for building the lectures - #363

Open
kp992 wants to merge 50 commits into
mainfrom
jb2
Open

[Experimental] Use jupyter-book 2.0 for building the lectures#363
kp992 wants to merge 50 commits into
mainfrom
jb2

Conversation

@kp992

@kp992 kp992 commented Jul 23, 2025

Copy link
Copy Markdown

Experimental setup for building the lectures with the QuantEcon MyST stack. This PR is built on top of #345.

Current toolchain

Both workflows now build with the QuantEcon fork of the MyST CLI and the new theme, so the Netlify preview shows the latest content rendered by the latest tooling.

Piece What the branch uses Where it is set
MyST CLI QuantEcon/mystmd main, cloned and built from source with bun; quantecon/VERSION.yml is printed to the log so every build records the qe-vN fork state it ran with (currently v1.10.1 (qe-v8)) .github/workflows/ci.yml, .github/workflows/build-ipynb.yml
Theme quantecon-theme.mystmd v2.2.0, pinned to the release zip lectures/myst.yml (site.template)
Build command myst build --html --execute .github/workflows/ci.yml
Content merged up to date with main

The theme moves off the archived QuantEcon/quantecon-theme bundle (which the branch was still pulling as a floating main.zip) onto a pinned release of the new theme repo. Bump the vX.Y.Z in the site.template URL to take a newer theme; the fork stays on main deliberately, so the preview tracks the latest tooling.

The build was not actually using the fork

Worth calling out separately, because it had been green and invisible: until this update the HTML preview was built by jupyter book build, which cannot use the fork. jupyter-book 2.x is a thin Python shim — jupyter_book/__main__.py execs a compiled mystmd bundle vendored inside its own wheel (jupyter_book/dist/jupyter-book.cjs) and exposes no hook to point it at another CLI. The globally installed fork was simply ignored, and only the build-ipynb workflow (which calls myst directly) ever exercised it.

The last run before the fix shows it plainly: the jupyter-book HTML build emitted 27 × 'output' unknown export output extension: exports/<page>.ipynb, because the per-page ipynb export is a fork feature (myst-to-ipynb, qe-v1) that upstream does not know about. The same commit built by the fork's myst build --ipynb emitted none and exported 23 clean notebooks. The HTML build now runs myst build --html --execute — the same engine and the same flags, since jupyter-book 2.x is mystmd, just our build of it.

Everything else in this update

  • Merged main. Brings in the new Polars lecture, the numba rewrite, the pandas_panel switch to remote CSVs, and the translation-sync workflows. The one conflict was ci.yml, where main and this branch have rewritten the same job for different builders — resolved in favour of this branch's job, keeping main's runner spec and action bumps.
  • myst.yml TOC re-synced with _toc.yml. It had drifted: autodiff and the new polars lecture were missing, workspace appeared twice, and one part title differed. The two files now list exactly the same 27 pages.
  • project.github corrected to lecture-python-programming — it pointed at lecture-python-programming.myst, which now only survives as a rename redirect. The theme derives the notebook-launch repo from this value plus a .notebooks suffix, so a stale name means broken launch buttons.
  • JAX is now installed in the build. Previous preview builds were rendering ModuleNotFoundError cells for jax_intro, autodiff and numpy_vs_numba_vs_jax, because this job installed only myst_requirements.txt while the jupyter-book 1.x job on main installs jax[cuda13] separately. Same install, same runner family.
  • CI actions moved to current majors and Node 20 → 24 (the theme's .nvmrc; it runs as a Remix server during myst build --html). This also clears the Node 20 runtime deprecation warnings. The unused configure-pages step is gone — this job deploys to Netlify, not Pages.
  • Removed committed execution artifacts (foo.py, newfile.txt, numbers.txt, output.txt, output2.txt, test_table.csv, us_cities.txt). All are written by %%file / %%writefile cells in the lectures themselves, all are matched by .gitignore, and none exist on main.

Still open

  • Nothing fails the build on a notebook execution error. Execution errors are reported and the build carries on, which is how the JAX failures above survived green builds. main gained a gate for the jupyter-book 1.x path in CI: gate the first jb build so notebook errors cannot pass green #588; the fork's CLI has myst build --strict for this, but it should be turned on only once the remaining build diagnostics are triaged, or it will fail on unrelated warnings.
  • Launch-button URLs are left on the theme defaults (<repo>.notebooks, branch main, notebooks at the repo root), matching the layout of lecture-python-programming.notebooks. Worth clicking through in the preview to confirm the page location resolves as expected.

@github-actions

github-actions Bot commented Jul 23, 2025

Copy link
Copy Markdown

@github-actions
github-actions Bot temporarily deployed to pull request July 23, 2025 01:19 Inactive
@kp992
kp992 requested a review from mmcky July 23, 2025 01:20
@mmcky

mmcky commented Jul 23, 2025

Copy link
Copy Markdown
Contributor

@kp992 thanks for opening this. Excellent work! It is exciting to see how close we are now.

From my review it looks like there a just a few issues and features we need before launch.

Bugs:

  1. LHS TOC menu flickers when using the Home page or a top level Part section. It is like it has an auto-stow feature that is triggering when pages are reloaded. It doesn't look great when pages are refreshed.
  2. Code block formatting has too much indentation for Solution blocks

Features:

  1. I see a bunch of new export notebooks being added to the yaml headers of each lecture. Do we need to do some development work on supporting the download notebook link in the theme?
  2. Is index support on the jb2 / mystmd roadmap?

- Add `markdown: commonmark` to all 24 lecture export configs so ipynb
  exports produce plain CommonMark markdown cells compatible with
  vanilla Jupyter Notebook, JupyterLab, and Google Colab
- Add build-ipynb.yml workflow that clones QuantEcon/mystmd@myst-to-ipynb,
  builds from source, exports all ipynb files, and audits for MyST leaks
- All 24 notebooks pass audit (0 MyST syntax leaks)

Uses QuantEcon/mystmd myst-to-ipynb branch which adds:
- CommonMark AST pre-transform (admonitions, math, figures, exercises, etc.)
- Identifier/label stripping to prevent (label)= prefixes
- Image directive stripping for plain ![alt](url) output
- Empty cell filtering and block marker removal
@mmcky

mmcky commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Thanks @mmcky for pushing this forward and fixing the issues. I saw the generated notebooks and they look great! One issue I found was about the solution rendering. The solution shows up as the normal markdown ```python code block instead of an executable block.

Thanks @kp992 would you mind raising an issue on https://github.com/QuantEcon/mystmd

Thanks @kp992 I think I have identified the root cause of this. QuantEcon/mystmd#5
Working on a fix.

@kp992

kp992 commented Feb 27, 2026

Copy link
Copy Markdown
Author

Thank you @mmcky. The issue looks resolved and the generated notebooks are awesome!!

mmcky added 3 commits May 7, 2026 15:27
# Conflicts:
#	.github/workflows/ci.yml
#	lectures/need_for_speed.md
#	lectures/numba.md
#	lectures/numpy_vs_numba_vs_jax.md
@github-actions
github-actions Bot temporarily deployed to pull request May 7, 2026 06:49 Inactive
mmcky added 2 commits May 14, 2026 15:30
Aligns the lecture build with the updated QuantEcon/mystmd workflow,
where main carries all squash-merged features (replacing the previous
quantecon integration branch). Also surfaces VERSION.yml in build
logs for diagnostic traceability of which qe-vN features are in use.
# Conflicts:
#	.github/workflows/ci.yml
@github-actions
github-actions Bot temporarily deployed to pull request May 14, 2026 05:44 Inactive
@mmcky

mmcky commented May 14, 2026

Copy link
Copy Markdown
Contributor
  • check if theme regression is occurring. Clicking on a chapter briefly shows a malformed webpage that disappears to the LEFT. NEEDS REVIEW.

mmcky and others added 3 commits July 31, 2026 16:08
Brings the branch up to date with main: the new Polars lecture, the numba
lecture rewrite, the pandas_panel switch to remote CSVs, the translation
sync workflows, and the jupyter-book 1.x CI changes.

The only conflict was .github/workflows/ci.yml, where main and this branch
have rewritten the same job for different builders. Resolved in favour of
this branch's jupyter-book 2.0 job, adopting main's runner spec
(volume=80gb/spot=false) and action bumps (checkout@v7,
upload-artifact@v7, actions-netlify@v4) on top of it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…oling

Theme: move site.template from the archived QuantEcon/quantecon-theme bundle
(main.zip) to a pinned quantecon-theme.mystmd release, v2.2.0 — the current
release, which carries the fancy-list rendering that pairs with the fork's
fancy-lists parser (qe-v8). Pinned rather than floating so a theme release
cannot change the build under us; bump the version in the URL to take a
newer one.

myst.yml also gets:

- project.github corrected to lecture-python-programming (it pointed at
  lecture-python-programming.myst, which only survives as a rename
  redirect). The theme derives the notebook-launch repo from this value
  plus a ".notebooks" suffix, so a stale name means broken launch buttons.
- toc brought back in line with _toc.yml: adds autodiff and the new polars
  lecture, drops the duplicate workspace entry from "Introduction to
  Python", and renames "The Scientific Libraries" to "Foundations of
  Scientific Computing".

CI: Node 20 -> 24 (the theme's .nvmrc; it runs as a Remix server during
`myst build --html`) and the remaining actions to current majors, which
also clears the Node 20 runtime deprecation warnings. Adds the JAX install
the jupyter-book 1.x workflow on main already does — without it the GPU
lectures execute to ModuleNotFoundError cells in the preview, which the
build does not fail on. Drops the unused configure-pages step; this job
deploys to Netlify, not Pages.

mystmd itself already comes from the QuantEcon fork's main branch, built
from source with bun, with quantecon/VERSION.yml logged for traceability.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
foo.py, newfile.txt, numbers.txt, output.txt, output2.txt, test_table.csv
and us_cities.txt are all written by the lectures themselves during
execution (%%file / %%writefile cells in getting_started, python_essentials,
python_advanced_features and debugging), and every one of them is matched
by .gitignore. They were picked up by the initial mystmd setup commit and
do not exist on main.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to pull request July 31, 2026 06:15 Inactive
The preview build was not using QuantEcon/mystmd at all. jupyter-book 2.x
is a thin Python shim: jupyter_book/__main__.py execs a compiled mystmd
bundle vendored inside its own wheel (jupyter_book/dist/jupyter-book.cjs)
and exposes no way to point it at a different CLI. So `jupyter book build`
ignored the fork this workflow installs globally and built the site with
upstream mystmd, while only the build-ipynb workflow (which calls `myst`
directly) ever exercised the fork.

The last run shows it plainly: the jupyter-book HTML build emitted 27 x
"'output' unknown export output extension: exports/<page>.ipynb", because
the per-page ipynb export is a fork feature (myst-to-ipynb, qe-v1) that
upstream does not know. The same commit built by the fork's `myst build
--ipynb` emitted none and exported 23 clean notebooks.

`myst build --html --execute` is the same engine and the same flags —
jupyter-book 2.x is mystmd — just our build of it. Dropping the
jupyter-book install also removes a second, conflicting mystmd from the
image. Workflow renamed to match what it now runs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mmcky

mmcky commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Refreshed against the current toolchain

Branch is up to date with main and now builds with the QuantEcon fork of the MyST CLI and the new theme repo. The PR description has been rewritten to describe the resulting setup.

Piece Before Now
MyST CLI (HTML build) upstream mystmd, vendored inside the jupyter-book wheel QuantEcon/mystmd mainv1.10.1 (qe-v8)
Theme QuantEcon/quantecon-theme floating main.zip (repo archived) quantecon-theme.mystmd v2.2.0, pinned release zip
Content 2 months behind main merged, conflict resolved — PR is mergeable again

The HTML build was never using the fork

This is the part worth reading. jupyter book build cannot use our fork, and had been quietly building the preview with upstream mystmd this whole time. jupyter-book 2.x is a thin Python shim: jupyter_book/__main__.py execs a compiled mystmd bundle vendored inside its own wheel (jupyter_book/dist/jupyter-book.cjs) and exposes no hook to point it at a different CLI. The npm install -g of the fork in this workflow was installing a CLI that the build step then ignored. Only build-ipynb.yml, which calls myst directly, was ever exercising the fork.

The evidence is in the last run before the fix — the jupyter-book HTML build emitted 27 × 'output' unknown export output extension: exports/<page>.ipynb, since the per-page ipynb export is a fork feature (myst-to-ipynb, qe-v1) that upstream doesn't know about. The same commit built by the fork's myst build --ipynb emitted none and exported 23 clean notebooks.

The HTML build now runs myst build --html --execute with the fork's CLI, and the pip install jupyter-book step is gone — it was only putting a second, conflicting mystmd on the image. Same engine and same flags either way; jupyter-book 2.x is mystmd, this is just our build of it.

Three other things the review turned up

  • The JAX lectures were rendering ModuleNotFoundError cells. This job installed only myst_requirements.txt, while the jupyter-book 1.x job on main installs jax[cuda13] separately, so jax_intro, autodiff and numpy_vs_numba_vs_jax had been executing to import errors through green builds. Same install added here.
  • myst.yml's TOC had drifted from _toc.ymlautodiff and the new polars lecture missing, workspace listed twice, one part title stale. The two files now list exactly the same 27 pages.
  • project.github pointed at lecture-python-programming.myst, which only survives as a rename redirect. The theme derives the notebook-launch repo from that value plus a .notebooks suffix, so a stale name means broken launch buttons. Corrected.

Also: Node 20 → 24 (the theme's .nvmrc), remaining actions to current majors (clears the Node 20 removal deprecation), the unused configure-pages step dropped since this job deploys to Netlify rather than Pages, and seven committed execution artifacts removed (foo.py, us_cities.txt, test_table.csv and friends — all written by %%file cells in the lectures, all gitignored, none present on main).

Left for a decision

Nothing fails the build on a notebook execution error — that is exactly how the JAX breakage stayed invisible. main gained a gate for the jupyter-book 1.x path in #588; the fork's CLI has myst build --strict for the same job here, but it is worth turning on only after the remaining build diagnostics are triaged, otherwise it will fail on unrelated warnings.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants