From 52ac4df73c7f327d99e6c5da6e9297930caeed06 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 15 Oct 2026 23:17:26 +0000 Subject: [PATCH] feat: slides inside the docs site + GitHub Pages deploy - packages.slides inlines each data-markdown deck into its .html (flake-parts/scripts/inline-markdown.py): the built deck opens from file:// and carries no .md for MkDocs to render - documentation build copies the built deck to /slides/ (mkdocs-preBuildHook); new Presentation page embeds it in an iframe - .github/workflows/pages.yml: nix flake check + nix build .#documentation, deploy to GitHub Pages on main (PRs check and build only) - docs updated for all of the above Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_0134mfNgkokU4oenUnqXigQz --- .github/workflows/pages.yml | 52 ++++++++++++++++++++++++++ README.md | 1 + documentation/docs/getting-started.md | 18 ++++++--- documentation/docs/nix.md | 4 +- documentation/docs/presentation.md | 24 ++++++++++++ documentation/docs/reveal-js.md | 18 +++++++-- documentation/mkdocs.yml | 1 + flake-parts/default.nix | 11 +++++- flake-parts/scripts/inline-markdown.py | 37 ++++++++++++++++++ flake-parts/slides.nix | 10 +++-- 10 files changed, 161 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/pages.yml create mode 100644 documentation/docs/presentation.md create mode 100644 flake-parts/scripts/inline-markdown.py diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..afd5975 --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,52 @@ +# Build the MkDocs site (with the slide deck at /slides/) using Nix and +# deploy it to GitHub Pages. Pull requests only check and build. +# +# One-time setup: Settings → Pages → Build and deployment → Source: +# "GitHub Actions". +name: pages + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +permissions: + contents: read + +# One deployment at a time; a newer push cancels an older pending one. +concurrency: + group: pages-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: cachix/install-nix-action@v31 + - name: Check (both builds + Nix lint) + run: nix flake check -L + - name: Build the site + run: | + nix build .#documentation -L + # Copy out of the read-only Nix store for the Pages upload. + cp -rL result _site + chmod -R u+w _site + - uses: actions/upload-pages-artifact@v3 + with: + path: _site + + deploy: + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index c7b73b2..cab5a11 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ the browser. ```text flake.nix inputs (nixpkgs, flake-parts, mkdocs-flake, reveal.js), locked in flake.lock flake-parts/ flake modules, auto-imported: docs settings, slides build, checks +.github/workflows/ pages.yml: check, build and deploy the docs site to GitHub Pages documentation/ MkDocs site: mkdocs.yml + docs/*.md slides/ reveal.js deck: index.html + slides.md ``` diff --git a/documentation/docs/getting-started.md b/documentation/docs/getting-started.md index 4fb1e4b..7ebbc33 100644 --- a/documentation/docs/getting-started.md +++ b/documentation/docs/getting-started.md @@ -77,10 +77,16 @@ nix fmt . # format the .nix files nix flake check # builds both sites and lints the Nix code ``` -## 6. Publish (example: GitHub Pages) +## 6. Publish to GitHub Pages -Any host that serves a folder works. For GitHub Pages, a workflow can run -`nix build .#documentation`, copy `result/` and upload it with -[`actions/upload-pages-artifact`](https://github.com/actions/upload-pages-artifact). -Put the slides in a subfolder of the same upload if you want both on one -site, for example `cp -rL result-1/. public/slides/`. +The repo ships `.github/workflows/pages.yml`. On every push to `main` it +runs `nix flake check`, builds the docs site (slides included under +`/slides/`) and deploys it to GitHub Pages. Pull requests run the same +checks and build without deploying. + +Turn it on once per repo: **Settings → Pages → Build and deployment → +Source: GitHub Actions**. The site then appears at +`https://.github.io//`. + +Any other static host works the same way: upload the contents of the +`nix build .#documentation` result. diff --git a/documentation/docs/nix.md b/documentation/docs/nix.md index 495cce0..bdb9751 100644 --- a/documentation/docs/nix.md +++ b/documentation/docs/nix.md @@ -11,6 +11,8 @@ flake.lock # exact versions of every input (generated, commit it) flake-parts/ ├── default.nix # formatter + MkDocs settings ├── slides.nix # the reveal.js build and the serve-slides app +├── scripts/ +│ └── inline-markdown.py # folds slides.md into index.html at build time ├── checks.nix # `nix flake check`: both builds + the Nix linters └── template.nix # lets `nix flake init -t` copy this repo (delete it in your copy if you like) documentation/ # the MkDocs site @@ -63,7 +65,7 @@ module sets options inside `perSystem`, for example `packages.slides` or | Command | Output | | --- | --- | -| `nix build .#documentation` | the docs website (from mkdocs-flake) | +| `nix build .#documentation` | the docs website, with the deck at `/slides/` | | `nix build .#slides` | the slide deck | | `nix run .#watch-documentation` | live docs preview | | `nix run .#serve-slides` | live slides preview | diff --git a/documentation/docs/presentation.md b/documentation/docs/presentation.md new file mode 100644 index 0000000..e09f9ec --- /dev/null +++ b/documentation/docs/presentation.md @@ -0,0 +1,24 @@ +# Presentation + +The slide deck from `slides/`, embedded in this site. Click it and use the +arrow keys, or open it on its own. + + + + + +!!! info "How the deck gets here" + `nix build .#documentation` builds the deck (`nix build .#slides`) + first and copies it into the site at `/slides/` before MkDocs runs + (`mkdocs-preBuildHook` in `flake-parts/default.nix`). The deck still + builds and works on its own, too. + + The live preview (`nix run .#watch-documentation`) serves only + `documentation/`, so the frame above is empty there. Preview the deck + with `nix run .#serve-slides`, or build the whole site and serve it: + `nix build .#documentation && python3 -m http.server -d result`. diff --git a/documentation/docs/reveal-js.md b/documentation/docs/reveal-js.md index b06b66d..3b6fc47 100644 --- a/documentation/docs/reveal-js.md +++ b/documentation/docs/reveal-js.md @@ -12,12 +12,12 @@ slides/ └── slides.md # the slides themselves, in Markdown ``` -When you build, Nix copies `slides/` and adds reveal.js under `reveal/`: +When you build, Nix copies `slides/`, folds `slides.md` into +`index.html`, and adds reveal.js under `reveal/`: ```text result/ -├── index.html -├── slides.md +├── index.html # with slides.md inlined └── reveal/ # reveal.js' prebuilt dist/: reveal.js, reveal.css, theme/, plugin/ ``` @@ -106,7 +106,17 @@ at the bottom of `index.html`. See the `index.html` loads `slides.md` with a web request, and browsers block those requests from pages opened straight from disk (`file://`). That is why the repo has `nix run .#serve-slides` instead of "double-click index.html". -Hosted on any web server, the built deck works as-is. + +The **built** deck does not have this problem: `nix build .#slides` copies +the Markdown into `index.html` itself (a ``, +and the inlined .md files are deleted. The built deck then needs no +fetch() (works from file://), and MkDocs never sees a stray .md file when +the deck is copied into the docs site. +""" + +import html +import pathlib +import re +import sys + +SECTION = re.compile( + r'[^>]*?)\sdata-markdown="(?P[^"]+)"(?P[^>]*)>\s*' +) + +root = pathlib.Path(sys.argv[1]) +inlined = set() +for page in root.rglob("*.html"): + text = page.read_text(encoding="utf-8") + + def inline(match): + src = (page.parent / match["src"]).resolve() + inlined.add(src) + body = html.escape(src.read_text(encoding="utf-8"), quote=False) + return ( + f'' + f"" + ) + + page.write_text(SECTION.sub(inline, text), encoding="utf-8") + +for src in inlined: + src.unlink() diff --git a/flake-parts/slides.nix b/flake-parts/slides.nix index 36165f1..9a33a82 100644 --- a/flake-parts/slides.nix +++ b/flake-parts/slides.nix @@ -9,9 +9,13 @@ in { # nix build .#slides → ./result is the static slide deck: the files in # slides/ plus reveal.js under reveal/ (index.html links reveal/...). - packages.slides = pkgs.runCommand "slides" {} '' - mkdir -p $out - cp -r ${../slides}/. $out/ + # Each `data-markdown="x.md"` deck gets its Markdown inlined into the + # .html (scripts/inline-markdown.py), so the built deck opens straight + # from disk and nests cleanly inside the MkDocs site (default.nix). + packages.slides = pkgs.runCommand "slides" {nativeBuildInputs = [pkgs.python3];} '' + cp -r ${../slides} $out + chmod -R u+w $out + python3 ${./scripts/inline-markdown.py} $out cp -r ${reveal} $out/reveal '';