The build tooling (the MyST plugin, the nma-kit command and the GitHub
Actions workflows) lives in the Neuromatch course kit, a separately
versioned project, published as @neuromatch/course-kit on npm and
neuromatch-course-kit on PyPI. Every course calls the kit’s reusable
workflows instead of carrying its own copy, and picks up kit fixes on its next
build. The @v0.1 in the workflow is the only version knob: the newest 0.1.x
(compatible updates), or an exact tag such as @v0.1.3 to freeze a finished course.
A new course gets one workflow from nma-kit init, .github/workflows/course.yml.
This book’s own copy is included below, so the page always shows what actually runs.
What runs, and when¶
On a pull request, the workflow checks your changes without publishing anything:
nma-kit checkvalidates the content rules: no.ipynbfiles intutorials/, every page with code cells has akernelspec, every{nma-video}/{nma-slides}directive is valid, every exercise has an{nma-solution}, and thenma:settings inmyst.ymlare well formed.nma-kit notebooks --dry-runchecks that every executable page converts.nma-kit render-scrollyruns every scrollytelling page (layout: scrolly, see W1D2 Tutorial 6) headless. A cell that raises fails the check.The whole site is built, so a broken page fails the check too.
On a push to main, the same steps run for real, in order, each one only if
the previous one passed:
nma-kit checknma-kit notebooksconverts each executable.mdtutorial to.ipynb, adds a Colab/Kaggle badge cell, turns{nma-video}/{nma-slides}and{nma-feedback}into notebook cells, and splits{nma-solution}/{nma-explanation}into a student notebook (links) and an instructor notebook (answers inline), plus the solution files.nma-kit publish-notebookspushesnotebooks/to the separatenotebooks-branch. The branch is created the first time, so a new course works on its first push.nma-kit render-scrollypre-renders the scrollytelling pages, so readers see real figures before they start Python.nma-kit prepare-siteadds Colab/Kaggle badges to the executable pages and, on pages with exercises, a hidden setup cell so “Run all” doesn’t stop at an unfinished exercise. This only happens in CI’s temporary checkout.myst build --htmlbuilds the book, and the next job deploys it to GitHub Pages.
Generated notebooks are never committed to main, which keeps main free of
generated files and avoids CI commit loops. Videos, slides, solution links and
feedback widgets need no extra step: the course kit’s MyST plugin renders them
during myst build.
# Copy to .github/workflows/course.yml in your course repo.
# Pull requests are checked and get a public preview on Cloudflare Pages (see
# the README, "Pull request previews"); pushes to main publish the notebooks
# and the site.
# @v0.1 = the newest 0.1.x release (compatible updates, applied on every build).
# Pin an exact version (e.g. @v0.1.3) to freeze a finished course.
name: Course
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened, closed]
workflow_dispatch:
jobs:
check:
if: github.event_name == 'pull_request' && github.event.action != 'closed'
uses: neuromatch/course-kit/.github/workflows/course-check.yml@v0.1
publish:
if: github.event_name != 'pull_request'
uses: neuromatch/course-kit/.github/workflows/course-publish.yml@v0.1
permissions:
contents: write
pages: write
id-token: write
# Needs the CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID secrets and the
# CLOUDFLARE_PROJECT variable; without them the deploy is skipped. Delete
# this job if the course does not want previews.
preview:
if: >-
github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository
uses: neuromatch/course-kit/.github/workflows/course-preview.yml@v0.1
with:
pr-number: ${{ github.event.pull_request.number }}
action: ${{ github.event.action == 'closed' && 'cleanup' || 'deploy' }}
cloudflare-project: ${{ vars.CLOUDFLARE_PROJECT }}
secrets: inherit
permissions:
contents: write
pull-requests: write
Running the same steps locally¶
uv venv && uv pip install -r requirements.txt neuromatch-course-kit
uv run nma-kit check
uv run nma-kit sync-assets # branding files, written to _nma/
uv run nma-kit notebooks --dry-run
uv run myst startSetting up GitHub Pages¶
Go to your repo Settings → Pages
Set Source to
GitHub ActionsPush any change to
mainto trigger the first build
Your book will be live at https://<your-org>.github.io/<your-repo>/. To use a
custom domain, set it under Settings → Pages → Custom domain; with the
GitHub Actions source no CNAME file is needed.