Skip to content

Latest commit

 

History

147 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QuantEcon Lecture Theme — for MyST Markdown

A dedicated MyST interactive book theme (@quantecon/lecture-theme) for the QuantEcon lectures and books, distributed as a zip attached to each GitHub Release.

  • Responsive and mobile ready
  • Notebook launch (Google Colab) with configurable repo, branch and paths
  • In-page live compute via Thebe (JupyterLite / Pyodide by default)
  • Git history in page headers ("Last changed" plus an inline changelog)
  • Full OpenGraph / Twitter card meta tags, and collapsible stderr on notebook cells
  • A docs/ feature reference mirroring the book theme's user guide
  • Page Footer based on MyST Content
  • Bundled QuantEcon brand assets

Downloads

When downloads are available on a page, a download button will appear in the top toolbar. The contents of the menu available from that button is configured via the download configuration of the MyST project and page. Typically, a download of the entire book as a PDF is provided along with downloads of each lecture in PDF and Notebook (md) form.

To achieve this the following configuration should be added to build and expose the downloads.

At the project level:

# myst.yml
project:
  ...
  exports:
    - id: book-pdf
      format: pdf
      template: plain_latex_book
      output: exports/quantecon-python-intro.pdf
  downloads:
    - id: book-pdf
      title: Book (PDF)

And then on each page:

# long_run_growth.md
exports:
  - format: pdf
    template: plain_latex_book
    output: exports/long_run_growth.pdf
downloads:
  - file: exports/long_run_growth.pdf
    title: Lecture (PDF)
  - file: ./long_run_growth.md
    title: Notebook (md)

Launch Notebooks

The launch notebooks capability mirrors the previous QuantEcon theme's, which shows the control only for a site that names a notebook repository. Nothing is assumed about repository naming: a site says where its notebooks are, or gets no Launch control.

The Launch control in the toolbar is a direct link to Google Colab, the single launch target — it provides GPU access for the lectures that need it. Two other targets are deliberately not offered today, each tracked as a demand-driven future request: BinderHub, which proved flaky in practice (#26), and a private JupyterHub, whose launcher entry was removed in #87 because no lecture repo had ever configured one. For running cells without leaving the page, see Live compute below.

Launch is opt-in: it appears only once a site names a notebook repository and turns a launch service on, under site.options in myst.yml (MyST's theme-options section; see Site options for the full list).

site:
  options:
    launch_notebook_repo: QuantEcon/lecture-foo.notebooks
    launch_colab: true

With either unset there is no Launch control. Nothing is derived from project.github, so a site without a notebooks repository cannot link readers to one that does not exist; set launch_notebook_repo only when the repository really is there.

Option Default Purpose
launch_notebook_repo (none) Notebook repository, as a full URL or org/repo
launch_notebook_branch main Branch in the notebook repo to launch from
launch_notebook_dir (none) Sub-directory within the notebook repo where the notebooks live
launch_notebook_source_dir (none) Path prefix stripped from the page location (e.g. a lectures/ source dir)
launch_colab (off) Offer Google Colab

Coming from quantecon-book-theme: nb_repository_urllaunch_notebook_repo, nb_branchlaunch_notebook_branch, nb_path_to_notebookslaunch_notebook_dir, path_to_docslaunch_notebook_source_dir, and launch_buttons.colab_urllaunch_colab: true.

Live compute (Thebe / JupyterLite)

In addition to launching a notebook elsewhere (Colab/Hub), the theme can run notebook cells in place via Thebe. This is opt-in per project through the standard MyST thebe config, set under project.thebe in myst.yml (the theme reads it from the project manifest, so it is project-level — not per-page frontmatter). The QuantEcon default is JupyterLite — Python runs entirely in the browser via Pyodide, with no server or Binder to host:

# myst.yml
project:
  thebe:
    lite: true

With this set, a Power toggle appears in the header toolbar (next to the Launch button) on notebook pages. Clicking it boots the in-browser kernel, after which Run / Restart / Clear take its place; cells then execute live. The toggle lives in the fixed header so it stays visible while scrolling, and only appears on notebook pages (desktop). It is the @myst-theme/jupyter notebook toolbar, relocated into the header via a portal.

Caveat: Pyodide runs pure-Python plus packages compiled for it (numpy, scipy, pandas, matplotlib, sympy). Packages that aren't available for Pyodide (e.g. numba, JAX) won't import, so live compute suits lectures whose runtime stack is Pyodide-compatible. Other backends are available through the same thebe config (binder: for BinderHub, server: for a hosted Jupyter server) if a project needs a full environment.

Git history in page headers

The page header shows a "Last changed: ⟨date⟩" control (aligned to the right of the author line) that expands an inline changelog listing the most recent commits touching that page — commit hashes link to GitHub, and a "full history" link opens the file's complete commit log (mirroring the quantecon-book-theme header). The changelog opens in place above the header's blue divider, pushing it down, so it stays adjacent to its toggle and clear of the lecture content.

The data is injected at build time by plugins/git-metadata.mjs, a MyST transform that runs git log --follow per source file and attaches { last_modified, changelog: [{hash, short_hash, author, date, message}] } to the page AST. Lecture repos load it by URL, pinned to the same theme release tag they build with, rather than vendoring copies:

# myst.yml
project:
  github: https://github.com/QuantEcon/lecture-python.myst # commit links target this repo
  plugins:
    - https://raw.githubusercontent.com/QuantEcon/quantecon-theme.mystmd/v3.0.0/plugins/git-metadata.mjs

The plugin is moving to the shared QuantEcon/quantecon-plugins.mystmd repository (QuantEcon/quantecon-plugins.mystmd#11); the in-repo copy is retired once that standalone release exists (#157). Until then the pinned URL above is the supported form.

Notes:

  • The header control renders nothing when no metadata is present, so projects without the plugin are unaffected.
  • A page can pin the control by hand with the same shape under site: in its frontmatter, as a YAML block string (git_metadata: | then the indented last_modified and changelog); it takes precedence over the injected data. tests/visual/fixture/features.md is an example.
  • The plugin is a silent no-op for untracked files, non-git checkouts, missing git, or a git log timeout (5s). Shallow CI clones (fetch-depth: 1) produce truncated history — use fetch-depth: 0 when building for deploy.
  • QE_GIT_METADATA_MAX caps changelog entries per page (default 6; myst-cli does not pass options to transform plugins, hence the environment variable). The expanded changelog does not scroll — it grows to fit — so this value is also what controls how tall it gets.
  • A page can pin or correct its history manually — set the same shape under site.git_metadata in the page frontmatter, which takes precedence over the injected data (this is how the visual fixture keeps snapshots deterministic).

Multilingual editions

A translated edition sets its language, direction and translators, and lists the sibling editions, under site.options (all declared in template.yml):

# myst.yml
site:
  options:
    current_language: fa        # BCP 47 code: document lang, current entry in the switcher
    enable_rtl: true            # dir="rtl" on the document (Arabic, Persian, Hebrew, Urdu)
    language_switcher_label: تغییر زبان   # tooltip / accessible name (default "Switch language")
    languages: |
      - code: en
        name: English
        url: https://python-programming.quantecon.org
      - code: fa
        name: فارسی
        url: https://quantecon.github.io/lecture-python-programming.fa
    translators: |
      - name: Adisankar Manoj Thanuja
        url: https://www.linkedin.com/in/adisankar-m-t/
    translators_label: ترجمهٔ   # default "Translated by"; an empty string hides the label
  • languages — with two or more entries the toolbar shows a globe-icon switcher linking to the same page in each edition (that edition's url plus the page path), and every page carries <link rel="alternate" hreflang> tags, with the first entry as x-default. The entry matching current_language is marked current.
  • translators — credited in the page header, at the end of the "Last changed" row, with the label in front. A page overrides the list in its own frontmatter under site:; the page value replaces the site value (never merges), and an explicitly empty value (translators: '') suppresses the credit on that page. The same values configure quantecon-book-theme.

languages and translators are written as YAML inside a block string (|). The MyST CLI validates site.options against the template's declared options and can only declare scalar types, so a bare list would be dropped; the theme parses the block. A real list is accepted too, should the engine ever pass one through.

One trap: a page whose site: frontmatter sets any of these keys has its whole site: block replaced by the validated keys, so an undeclared site.git_metadata on the same page is lost. Keep the two on different pages.

Meta tags

Every page carries the OpenGraph and Twitter card set the Sphinx lecture sites emit: og:title, og:description, og:type (website), og:site_name, og:url, og:image, og:locale, and twitter:card, twitter:site, twitter:creator, twitter:title, twitter:description, twitter:image. Four site.options keys feed them: site_url (the public URL, for og:url; myst's site.domains does not reach the theme), twitter, and the two image URLs og_logo_url / twitter_logo_url, named as in the book theme so a lecture repo copies its values across. A page's own thumbnail takes precedence for og:image.

Every page also carries a <link rel="canonical">, from the same site_url and built by the same function as og:url, so the two always agree. The home page's canonical is the site root, and every URL takes the trailing-slash form the build actually serves. With site_url unset neither is emitted — what Sphinx does without html_baseurl.

Collapsible stderr

A notebook cell's stderr stream is folded behind a "⚠ Code warnings" disclosure, closed by default, as on the Sphinx sites; stdout in the same cell stays visible. It is a native <details>, so it works without JavaScript.

Site options

Everything the theme reads from site.options is declared in template.yml. That list is not documentation only: the MyST CLI validates site.options against it and drops any key the template does not declare, so an undeclared option never reaches the theme (#173). Template options are scalar-only, so the structured ones are written as a YAML block inside a string (key: |), which the theme parses.

Option Scope Purpose
twitter site Handle for the twitter:site / twitter:creator card meta tags
site_url site The site's public URL, for the canonical link and og:url (Meta tags)
og_logo_url, twitter_logo_url site Site-level images for og:image / twitter:image when a page has no thumbnail (Meta tags)
favicon site Favicon file, relative to myst.yml; served at /favicon.ico (the QuantEcon lectures favicon when unset)
analytics_google, analytics_plausible site Analytics IDs, rendered by @myst-theme/site
hide_toc, hide_search site or page Hide the contents drawer / the search control
launch_notebook_repo, launch_notebook_branch, launch_notebook_dir, launch_notebook_source_dir, launch_colab site Notebook launcher (Launch buttons)
current_language, enable_rtl, languages, language_switcher_label site Multilingual editions (below)
translators, translators_label site or page Translator credit in the page header
git_metadata page YAML block pinning the "Last changed" control by hand (Git history)

A page-level value goes under site: in the page's frontmatter and is validated against the same list. Options carry no defaults in template.yml (a declared default would be written into every page's validated block and override the site-wide value); defaults live in the code that reads each one.

Usage with MyST

Point your project's site.template at a pinned release zip:

# myst.yml
site:
  template: https://github.com/QuantEcon/quantecon-theme.mystmd/releases/download/v3.0.0/quantecon-theme.zip

Pin a specific version rather than tracking a branch, and bump it deliberately: the releases page carries the changelog entry for each version, including anything consumers need to change.

Then start the local server:

myst start

Open up http://localhost:3000 and you should be ready to go!

Development

After cloning the repository, install the packages and start the dev server (with CSS watch and hot reload):

npm install
npm run dev

To preview against real MyST content instead, run a headless content server in your content project (myst start --headless) alongside the theme dev server.

See CONTRIBUTING.md for the full development setup, available scripts, and the test suites, and tests/visual/README.md for the visual-regression harness.

Release

Releases are cut by pushing a vX.Y.Z git tag: the release.yml workflow builds the theme and publishes a GitHub Release with quantecon-theme.zip attached, using that version's CHANGELOG.md section as the release notes. The step-by-step flow is documented in CONTRIBUTING.md.

About

QuantEcon Theme for mystmd

Resources

Contributing

Security policy

Stars

1 star

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages