Skip to content

Launch control cannot be turned off and links to a nonexistent notebooks repo on sites without one #205

Description

@mmcky

Part of #147 (parity study 2026-09-11 — content correctness).

Revised in place 2026-09-11 after the maintainer review:

  • Decided: the Launch control becomes opt-in and explicitly configured, with option names designed for more launch services.
  • Deferred: whether and where the theme checks that a notebook exists before showing Launch. The options are documented below.

The revision is recorded in the comments.

Problem

The Launch control (in the desktop toolbar and the mobile overflow menu) appears on every page of any project that sets project.github. It opens Colab on a notebook repository whose name the theme guesses: the source repository, minus any .myst suffix, plus .notebooks. Only launch_repo_url or launch_repo_suffix override the guess, and no option hides the control. A site without a notebooks repository therefore links readers to Colab on a repository that does not exist. For example, lecture-wasm's /cobweb/ opens https://colab.research.google.com/github/QuantEcon/lecture-wasm.notebooks/blob/main/cobweb.ipynb, and that repository returns 404 (verified 2026-09-11).

The book theme never guesses. It shows Launch only when nb_repository_url is set (layout.html L418-L420, launch.py L40), and adds each service only when that service is configured: Colab needs launch_buttons.colab_url (launch.py L124-L129).

Where this theme does it:

  • The notebook repository comes from project.github, and the only early return is a missing repo or page location (LaunchButton.tsx L15-L31).
  • The name is always derived as source plus suffix, unless launch_repo_url is set (launchUrls.ts L30-L43).
  • Five launch_* string options change the URL, and none turns the control off (template.yml L106-L123).

What the lecture repositories have (verified 2026-09-11)

Group Repositories Notebooks repository Sphinx site today This theme today
Configured, and the repository exists 13: lecture-python-intro, lecture-python-programming, lecture-python.myst, lecture-python-advanced.myst, lecture-jax, continuous_time_mcs, lecture-dle, lecture-eqm, lecture-stats, lecture-tools-techniques, lecture-julia.myst, lecture-datascience.myst Exists, and matches nb_repository_url Launch works Launch works (the guessed name happens to match)
Not configured 5: lecture-wasm; lecture-python-programming.fa, .fr, .zh-cn, .ml None No Launch Dead link (live on lecture-wasm)
Configured, but the repository is missing 3: lecture-dp, lecture-python.zh-cn, lecture-intro.zh-cn nb_repository_url points at a 404 Dead link on every page Dead link

The last row is fixed on the Sphinx side by QuantEcon/lecture-dp#60, QuantEcon/lecture-python.zh-cn#279 and QuantEcon/lecture-intro.zh-cn#305. Each removes the dead nb_repository_url, following QuantEcon/lecture-python-programming.fa#145.

Decision (2026-09-11)

  1. Opt-in and explicit. Launch renders only when a notebook source is configured and at least one launch service is enabled. The theme stops guessing: the derivation from project.github, the .myst rule and launch_repo_suffix all go.

  2. Flat option names now, shaped for nesting later. Theme options can only be boolean, string, number, choice or file, in both the QuantEcon mystmd fork and upstream, so a nested block cannot be declared yet. Template options can only be scalars, so site templates pack lists and nested settings into YAML strings mystmd#112 asks for structured options. Each flat name is the future nested path with underscores, so the migration is mechanical:

    Option (flat, now) Nested, once mystmd supports it Replaces Sphinx equivalent
    launch_notebook_repo launch.notebook.repo launch_repo_url nb_repository_url
    launch_notebook_branch (default main) launch.notebook.branch launch_branch nb_branch
    launch_notebook_dir launch.notebook.dir launch_notebooks_path nb_path_to_notebooks
    launch_notebook_source_dir launch.notebook.source_dir launch_source_path path_to_docs
    launch_colab launch.colab (implicit today) launch_buttons.colab_url
    launch_notebook_url (future) launch.notebook.url Update Colab badge URLs to support notebooks on gh-pages quantecon-book-theme#359 (notebooks served from the site)
    launch_binderhub_url, launch_jupyterhub_url (future) launch.binderhub_url, launch.jupyterhub_url launch_buttons.binderhub_url, launch_buttons.jupyterhub_url

    launch_repo_suffix is removed. All names are snake_case, like every other theme option.

  3. Launch services are kept apart from the notebook source. The launch_notebook_* group says where the notebook lives; launch_colab and the future service keys say what can open it. One source serves every service, so a service is not a property of the notebook. With more than one service enabled, the control becomes a menu, and that needs no config change.

  4. Migration. A lecture repository sets launch_notebook_repo only if that repository exists; the step is on the migration checklist (Lecture repos moving off the Sphinx theme have no checklist of what myst.yml and CI must now set #209).

    • lecture-wasm loses its dead link at its next theme bump, with no config change.
    • lecture-python-programming's jb2 branch adds launch_notebook_repo and launch_colab: true to keep its Colab link.

Deferred: checking the notebook exists before Launch is shown

The maintainer wants a failsafe, so that Launch never opens a missing notebook. Where that check runs is not decided yet. Current thinking: an in-page script that shows Launch only when it finds the referenced notebook.

Approach How it works For Against
In-page failsafe (current thinking) Launch starts hidden. A script requests the page's notebook, for example HEAD https://raw.githubusercontent.com/<repo>/<branch>/<path>.ipynb, and reveals the control only on success. raw.githubusercontent.com allows cross-origin requests and returns 404 for a missing repository (checked 2026-09-11) Accurate per page; catches a repository renamed or emptied after the build; no build change One request to GitHub per page view (cacheable for the session); the control appears after load; readers without JavaScript, or where GitHub is blocked, never see it
Build-time check The theme fetches the notebook repository's file list once per build, and renders Launch only on pages whose notebook is listed Static, repeatable output; no requests from readers Needs network during the build, and a GITHUB_TOKEN in CI (the unauthenticated GitHub API allows 60 requests an hour); goes stale if the repository changes after the build
Notebooks served from the site Notebooks are published with the site (QuantEcon/quantecon-book-theme#359, or the fork's ipynb export), so the build knows which exist No check needed, and no companion repositories Relies on Colab opening a notebook by URL (the claim in QuantEcon/quantecon-book-theme#359, not verified here), and on every site publishing its notebooks

Whichever approach is chosen:

  • Fail closed: hide the control on a timeout or error.
  • Keep the toolbar steady: no layout shift and no empty slot (the toolbar's optional slots use empty:hidden).
  • Decide per page.
  • Test the hidden state.

Acceptance criteria

  • Launch (desktop toolbar and mobile overflow menu) renders only when launch_notebook_repo is set and launch_colab is true. With either unset, there is no Launch control and no empty toolbar slot.
  • The Colab URL is built from launch_notebook_repo, launch_notebook_branch, launch_notebook_dir and launch_notebook_source_dir, and nothing is derived from project.github. launch_repo_suffix and the .myst rule are gone.
  • The options are declared in template.yml and listed in docs/configuration.md.
  • docs/launch.md and the README explain the options, map them from the Sphinx keys, and say that a site without a notebook source shows no Launch.
  • tests/unit/launch-urls.test.mjs covers the new options. The visual fixture sets launch_notebook_repo and launch_colab for the launch-colab test, and a new test asserts that no Launch control renders without them.
  • The CHANGELOG records the opt-in default and the renamed and removed options, as a breaking change for sites that relied on the guessed repository.
  • The deferred existence check is either implemented as decided above, or split into its own issue before this one closes.
  • After the release, live lecture-wasm shows no Launch link, and the jb2 build keeps its Colab link with the two new options.

Context

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is wrong or broken in a lecture or buildhigh-priorityAddress soon

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions