Skip to content

[Experimental] Build the lectures with QuantEcon/mystmd instead of jupyter-book - #363

Open
kp992 wants to merge 64 commits into
mainfrom
jb2
Open

[Experimental] Build the lectures with QuantEcon/mystmd instead of jupyter-book#363
kp992 wants to merge 64 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, cloned and built from source with bun, but the two workflows differ: ci.yml is pinned to the exact SHA 96ee78f5 so failures stay bisectable, while build-ipynb.yml clones --branch main and so tracks the fork's latest. quantecon/VERSION.yml is printed to the log, so every build records the qe-vN state it ran with — the ipynb build is currently on qe-v10, the HTML build on the pinned June engine .github/workflows/ci.yml (pinned), .github/workflows/build-ipynb.yml (main)
Theme quantecon-theme.mystmd v3.0.0, pinned to the release zip (taken in #629) 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. At the time this mattered because the theme derived the notebook-launch repo from the value plus a .notebooks suffix; theme v3.0.0 removed that derivation, so project.github now only drives the commit and "edit this page" links, and the launch repository is named explicitly (see chore: take theme v3.0.0, migrating the launch and footer config #629).
  • 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. Resolved by chore: take theme v3.0.0, migrating the launch and footer config #629. Theme v3.0.0 makes Launch opt-in, so site.options now names launch_notebook_repo, launch_notebook_source_dir and launch_colab, ported from lectures/_config.yml rather than invented; the branch is left unset because main is the default. Confirmed on that PR's preview: the button resolves to …/lecture-python-programming.notebooks/blob/main/need_for_speed.ipynb.
  • The ci.yml fork pin's comment is out of date. It says the SHA is "the exact SHA of the fork's main (unmoved since 2026-06-12)", but the fork's main has since moved to c1f274b8a (2026-09-10) and several qe-vN checkpoints have landed. The pin itself is a deliberate choice — it keeps failures bisectable — but the HTML build is now running a materially older engine than build-ipynb.yml, which is worth a conscious decision rather than drift.

@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
@kp992 kp992 added the do-not-merge Approved-looking but must not be merged yet (hold / pin) label Jul 23, 2025
@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
@DrDrij

DrDrij commented Aug 18, 2026

Copy link
Copy Markdown
Member

Netlify preview only, not a production concern: assets here are served with cache-control: public,max-age=0,must-revalidate, so every navigation makes a blocking revalidation round-trip (~390ms for a 304 with 0 bytes) before first paint. GitHub Pages serves max-age=600, so the deployed lectures are unaffected. If it is worth making the preview behave like production, a _headers file with /build/_assets/* Cache-Control: public,max-age=31536000,immutable is safe — those filenames are content-hashed, so a rebuild changes the URL.

Takes the theme from v2.2.0 to v2.3.0, per the release notes in
QuantEcon/quantecon-theme.mystmd — git-history page headers (automatic,
from this repo's git log at build time), opt-in in-page live compute
via project.thebe (not enabled here), and CDN-free stylesheets
(KaTeX/jupyter-matplotlib self-hosted, Font Awesome dropped), so maths
renders correctly where jsdelivr/cdnjs are blocked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mmcky

mmcky commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

@DrDrij I have just updated this to the latest release of quantecon-theme.mystmd incorporate recent merges.

mmcky and others added 2 commits August 20, 2026 14:16
Resolves the two ci.yml conflicts, both from main evolving steps that
jb2 rewrote for the mystmd toolchain:

- Install JAX: took main's side — the jax 0.11.0 pin rationale comment
  (jax 0.11.1 hangs fori_loop on CPU paths) and the numpyro install
  apply to the executed lectures regardless of build toolchain.
- The old jupyter-book steps (texlive, build-cache download, the
  jb clean prune from #616, sphinx-tojupyter): kept jb2's side — these
  steps do not exist in the myst pipeline, which builds cold with no
  restored sphinx cache, so the staleness problem the prune step
  addresses cannot occur here.

The execution-cache key hashes ci.yml, so this merge forces a cold
build — the pin, numpyro, and the v2.3.0 theme bump are all validated
by real execution rather than replayed outputs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Takes the icon-only search trigger, PT Serif headings, QuantEcon-blue links,
the Colab-only launcher and the first-paint fixes released today. Bumped
from v2.3.0, so v2.3.1 (static-build asset URLs) and v2.4.0 (content
typography, inline-code regression) come along too.

See QuantEcon/quantecon-theme.mystmd/releases/tag/v2.5.0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@mmcky

mmcky commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Bumped the theme pin in lectures/myst.yml from v2.3.0 to v2.5.0 (7a392b8), released today. Between those tags the theme picked up the static-build asset URL fixes (2.3.1), lecture content typography and the inline-code backticks regression fix (2.4.0), and in 2.5.0 the icon-only search trigger, PT Serif headings on the Sphinx scale, QuantEcon-blue content links, the Colab-only launcher (the Private JupyterHub option is gone), and the back-to-top / FOUC first-paint fixes. Release notes: https://github.com/QuantEcon/quantecon-theme.mystmd/releases/tag/v2.5.0. No other change on the branch; the existing conflict with main is untouched.

# Conflicts:
#	.github/workflows/ci.yml
Takes the QuantEcon code-token palette and seoul256 text colours (Phase 3),
the language switcher with hreflang alternates, right-to-left support and
the translator credit (Phases 4-5). No new site options are set here yet;
the multilingual ones are for the translated editions.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@mmcky

mmcky commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Bumped the pinned theme to v2.6.0 in b9524ff. It brings the QuantEcon code-token palette and seoul256 text colours (Phase 3), and the language switcher, hreflang alternates, RTL support and translator credit (Phases 4–5). This edition sets none of the new multilingual options, so the only visible change here is the code and text colouring; the switcher appears once languages lists the translated editions.

Patch release carrying the fix for QuantEcon/quantecon-theme.mystmd#186:
on the Netlify preview, pressing Back after following an in-page anchor
replaced the page with an "Application Error" screen, and the "Top"
control did a full reload. No configuration changes are needed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@mmcky

mmcky commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Pinned theme bumped to v2.6.1, the patch release carrying the fix for QuantEcon/quantecon-theme.mystmd#186 (Back after an in-page anchor showed an "Application Error" screen on the Netlify preview; "↑ Top" did a full reload). No configuration changes. The preview built from this commit is the first real-content check of that fix.

v2.7.0 carries the last items of the book-theme parity gate: the pinned,
scroll-tracking "On this page" panel with nested subsections
(QuantEcon/quantecon-theme.mystmd#182), collapsible stderr warnings and the
full OpenGraph/Twitter card set (QuantEcon/quantecon-theme.mystmd#92), and a
layout correction for desktop windows 1280-1327px wide
(QuantEcon/quantecon-theme.mystmd#198). No configuration changes are needed.

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

mmcky commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Pinned theme bumped to v2.7.0 in 41b1f83. It carries the last items of the book-theme parity gate: the pinned, scroll-tracking "On this page" panel with nested subsections (QuantEcon/quantecon-theme.mystmd#182), stderr output folded behind a "Code warnings" disclosure (QuantEcon/quantecon-theme.mystmd#92), and a layout correction for desktop windows 1280–1327px wide (QuantEcon/quantecon-theme.mystmd#198). No configuration changes are needed; this branch sets no site.options, so of the new OpenGraph/Twitter tags only og:type and og:site_name appear.

v3.0.0 is a breaking release for this repo's config: the five `launch_*`
options are replaced, and a site that bumps the pinned theme without
editing `myst.yml` silently loses its Launch control.

The launch values are ported from the Sphinx build rather than invented --
`nb_repository_url` becomes `launch_notebook_repo` and `path_to_docs`
becomes `launch_notebook_source_dir`, with `launch_colab: true` standing in
for the `launch_buttons.colab_url` entry. The branch is left unset because
`main` is the default. Nothing is derived from `project.github` any more,
so the comment above it that said otherwise is corrected.

`site.parts.footer` and `lectures/footer.md` are removed: the theme renders
the licence notice by default from v3.0.0, and declaring a footer part
replaces that whole block. The default is a superset of what the file had
-- it adds the "A theme by QuantEcon" credit the Sphinx sites carried, which
footer.md had dropped. `lectures/_static/ccbysa.png` goes with it, since the
badge is now an inline SVG in the theme and nothing else referenced it.

`site_url` comes from the Sphinx build's `html.baseurl` and is what makes
the theme emit a canonical link and `og:url`.

`need_for_speed.md` and `polars.md` lose their `{raw} jupyter`
notebook-header blocks, rewritten out by the theme repo's
`scripts/rewrite-raw-blocks.mjs`: mystmd renders no `raw` node, so each
block's own source was reaching readers as escaped text under the page
title.

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

mmcky commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Theme v3.0.0 is now on this branch: #629 merged into jb2 as 69ce7e5fd.

Three things in the description above are now out of date, listed here rather than edited in so the history stays readable.

The toolchain table says theme v2.2.0. It is v3.0.0 as of #629 — and the table had already drifted, since lectures/myst.yml was pinned at v2.7.0 before this. v3.0.0 is the release that closes the book-theme parity gate.

The project.github note no longer holds. It says the theme derives the notebook-launch repo from that value plus a .notebooks suffix, so a stale name means broken launch buttons. v3.0.0 removed that derivation entirely: Launch is opt-in and the repository is named explicitly. project.github still drives the commit and "edit this page" links, so keeping it correct matters for a different reason now.

The "Still open" bullet about launch defaults is resolved. The URLs are no longer on theme defaults — site.options now carries launch_notebook_repo, launch_notebook_source_dir and launch_colab, ported from lectures/_config.yml (nb_repository_url, path_to_docs, launch_buttons.colab_url) rather than invented, with the branch left unset because main is the default. Verified on the #629 preview: the button resolves to …/lecture-python-programming.notebooks/blob/main/need_for_speed.ipynb, so the page location does resolve as that bullet asked someone to confirm.

Also landed in #629, for completeness: lectures/footer.md and the then-orphaned _static/ccbysa.png are gone, because v3.0.0 renders the licence footer by default and a declared footer part replaces it — the default is a superset, restoring the "A theme by QuantEcon" credit the file had dropped. site_url is set from the Sphinx html.baseurl, which is what makes the theme emit a canonical link and og:url. And the {raw} notebook-header blocks are rewritten out of need_for_speed.md and polars.md, so their source no longer reaches readers as escaped text under the page title.

The HTML build pins an exact SHA so failures stay bisectable, which is the
right call -- but the pin had not moved since 2026-06-12 while the fork's
`main` gained 40 commits, so it was building with `qe-v8` while
build-ipynb.yml, which clones `main`, is on `qe-v10`. The two workflows
were rendering the same lecture commit with materially different engines.

Now pinned to c1f274b8a (2026-09-10, `qe-v10`). The comment no longer
claims the SHA *is* the fork's main, since that is what went stale: it now
records when the SHA was taken and that bumping is a deliberate act.

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

mmcky commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Engine bumped in f1c7a8d55: the ci.yml fork pin moves from 96ee78f5 (2026-06-12, qe-v8) to c1f274b8a (2026-09-10, qe-v10). Still an exact SHA rather than a branch — the pin exists so failures stay bisectable, so only its value changed, and the comment above it now records when the SHA was taken instead of claiming it is the fork main.

The reason for bumping: the pin had fallen 40 commits behind, so the HTML build was rendering with qe-v8 while build-ipynb.yml — which clones --branch main — was already on qe-v10. The same lecture commit was being built by two materially different engines depending on which workflow you looked at.

Worth reading this run's log rather than just its check mark. Per the "Still open" note above, execution errors are reported without failing the build, so a green run does not by itself establish that the newer engine is clean.

@mmcky

mmcky commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Followed my own advice and read the log rather than the check mark. The engine move is clean.

Both builds pass (HTML 4m50s, ipynb 2m04s), and the bump is confirmed active in the logs: the previous run recorded qe_version: qe-v8, this one records qe-v10.

Diagnostics are unchanged across the 40 commits of engine:

before (qe-v8) after (qe-v10)
⛔ lines 24 24
error 6 6
warning 10 10
unknown directive 1 1

For the record, those 24 ⛔ lines are two known classes and neither is an execution failure: 23 are one-per-page Resource "exports/<page>.ipynb" in downloads should be a URL or path to static file — the downloads entry names an ipynb that the HTML build does not produce, since build-ipynb.yml is what creates them — and 1 is status.md:16 unknown directive: nb-exec-table, the Sphinx directive with no mystmd counterpart.

Worth noting against the "Still open" item above: there are currently zero cell-execution errors in the build, so the "errors are reported but do not fail the build" hazard is latent rather than active right now, and this green run means what it appears to mean.

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

Labels

do-not-merge Approved-looking but must not be merged yet (hold / pin)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants