From ed4ff72166cbf2e198b0a044e90b09535f86e0be Mon Sep 17 00:00:00 2001
From: scriptautomate-bc <204508229+scriptautomate-bc@users.noreply.github.com>
Date: Mon, 13 Jul 2026 16:05:03 -0500
Subject: [PATCH 1/3] Pull from npm, don't save to source repo
---
.devcontainer/Dockerfile | 10 ++++
.devcontainer/devcontainer.json | 15 +++---
.github/workflows/gh-pages.yml | 9 ++++
.github/workflows/pr-checks.yml | 9 ++++
.gitignore | 2 +
.node-version | 1 +
README.md | 13 +++++
themes/pydata/.gitignore | 1 +
themes/pydata/hugo.toml | 35 ++++++++++++
themes/pydata/layouts/_partials/head.html | 2 +-
.../layouts/_partials/head/bootstrap-js.html | 15 ++++++
.../layouts/_partials/head/fontawesome.html | 15 ++++++
themes/pydata/layouts/baseof.html | 2 +-
themes/pydata/package-lock.json | 50 ++++++++++++++++++
themes/pydata/package.json | 9 ++++
themes/pydata/static/scripts/bootstrap.js | 3 --
themes/pydata/static/scripts/fontawesome.js | 3 --
.../static/styles/pydata-sphinx-theme.css | 8 +--
.../fontawesome/webfonts/fa-brands-400.woff2 | Bin 110088 -> 0 bytes
.../fontawesome/webfonts/fa-regular-400.woff2 | Bin 18924 -> 0 bytes
.../fontawesome/webfonts/fa-solid-900.woff2 | Bin 114740 -> 0 bytes
21 files changed, 183 insertions(+), 19 deletions(-)
create mode 100644 .node-version
create mode 100644 themes/pydata/.gitignore
create mode 100644 themes/pydata/layouts/_partials/head/bootstrap-js.html
create mode 100644 themes/pydata/layouts/_partials/head/fontawesome.html
create mode 100644 themes/pydata/package-lock.json
create mode 100644 themes/pydata/package.json
delete mode 100644 themes/pydata/static/scripts/bootstrap.js
delete mode 100644 themes/pydata/static/scripts/fontawesome.js
delete mode 100644 themes/pydata/static/vendor/fontawesome/webfonts/fa-brands-400.woff2
delete mode 100644 themes/pydata/static/vendor/fontawesome/webfonts/fa-regular-400.woff2
delete mode 100644 themes/pydata/static/vendor/fontawesome/webfonts/fa-solid-900.woff2
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 464ae9c..0a64b34 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -16,5 +16,15 @@ RUN HUGO_VERSION="$(cat /tmp/.hugo-version)" \
&& apt-get install /tmp/hugo.deb -y \
&& rm /tmp/hugo.deb /tmp/.hugo-version
+# Install Node.js (needed to `npm ci` the FontAwesome/Bootstrap build-time
+# deps in themes/pydata). Version is pinned in .node-version at the repo
+# root — the same file CI's actions/setup-node reads — so the devcontainer
+# and GitHub Actions never drift apart.
+COPY .node-version /tmp/.node-version
+RUN NODE_VERSION="$(cat /tmp/.node-version)" \
+ && curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz" -o /tmp/node.tar.xz \
+ && tar -xJf /tmp/node.tar.xz --strip-components=1 -C /usr/local \
+ && rm /tmp/node.tar.xz /tmp/.node-version
+
# Help avoid "unsupported locale setting" in Sphinx
RUN echo "export LC_ALL=C.UTF-8" > ~/.bashrc
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index abe7bc6..c59e473 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -17,17 +17,18 @@
},
// Features to add to the dev container. More info: https://containers.dev/features.
- // "features": {
- // node / npm is required for markdownlint-cli2
- // By default, installs lts version
- // "ghcr.io/devcontainers/features/node:1": {}
- // },
+ // Node.js itself is installed directly in the Dockerfile (pinned via the
+ // root .node-version file), not via this feature — avoids two divergent
+ // install paths.
+ // "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
- // Use 'postCreateCommand' to run commands after the container is created.
- // "postCreateCommand": ""
+ // Install the theme's build-time npm deps (FontAwesome/Bootstrap) after
+ // the workspace is mounted — a Dockerfile RUN step would get shadowed by
+ // the workspace bind mount, since node_modules isn't part of the repo.
+ "postCreateCommand": "cd themes/pydata && npm ci",
// There is also a postStartCommand that executes every time the container starts.
// The parameters behave exactly like postCreateCommand, but the commands execute on start rather than create.
diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml
index 27fcccc..8974130 100644
--- a/.github/workflows/gh-pages.yml
+++ b/.github/workflows/gh-pages.yml
@@ -49,6 +49,15 @@ jobs:
uses: actions/checkout@v4
- name: Install Hugo CLI
uses: ./.github/actions/setup-hugo
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.node-version'
+ cache: 'npm'
+ cache-dependency-path: themes/pydata/package-lock.json
+ - name: Install npm dependencies
+ working-directory: themes/pydata
+ run: npm ci
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml
index 3a4aa3f..497db6d 100644
--- a/.github/workflows/pr-checks.yml
+++ b/.github/workflows/pr-checks.yml
@@ -27,6 +27,15 @@ jobs:
uses: actions/checkout@v4
- name: Install Hugo CLI
uses: ./.github/actions/setup-hugo
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.node-version'
+ cache: 'npm'
+ cache-dependency-path: themes/pydata/package-lock.json
+ - name: Install npm dependencies
+ working-directory: themes/pydata
+ run: npm ci
- name: Build with Hugo
env:
HUGO_CACHEDIR: ${{ runner.temp }}/hugo_cache
diff --git a/.gitignore b/.gitignore
index dfb1e1c..b2cf406 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,5 @@ static/images/.DS_Store
.env.*
*.pem
*.key
+sandbox/
+node_modules/
diff --git a/.node-version b/.node-version
new file mode 100644
index 0000000..ba33190
--- /dev/null
+++ b/.node-version
@@ -0,0 +1 @@
+20.19.2
diff --git a/README.md b/README.md
index 15e6049..cd6eb0c 100644
--- a/README.md
+++ b/README.md
@@ -8,12 +8,17 @@ This repository is for the main static site of https://saltproject.io, built wit
- The exact version pinned for this project is tracked in the root `.hugo-version` file. The devcontainer and CI both install that exact version automatically (see `.devcontainer/Dockerfile` and `.github/actions/setup-hugo`), so it only needs to be updated in one place.
- Must be the `extended` version, and at least the minimum declared in the vendored `themes/pydata` theme's `hugo.toml` (`module.hugoVersion.min`).
- This was built with the `extended` version of Hugo, which is required.
+- Node.js — version pinned in the root `.node-version` file, same single-source-of-truth pattern as `.hugo-version`. Needed to install the theme's FontAwesome/Bootstrap build-time dependencies (see [FontAwesome and Bootstrap](#fontawesome-and-bootstrap-npm-at-build-time)).
- Git
- Python 3.14+ (only needed to run `scripts/validate-tags.py` locally)
### Build a local preview
```bash
+# Install the theme's build-time npm dependencies (FontAwesome/Bootstrap) —
+# only needs to be re-run when themes/pydata/package.json changes.
+cd themes/pydata && npm ci && cd -
+
# Serves for viewing changes locally
# Dynamically loads updates when changes happen in repo
hugo serve
@@ -195,6 +200,14 @@ The `scripts` folder holds standalone helper scripts used in local development a
- `.github/workflows/gh-pages.yml` — builds the site on every push, and deploys it to GitHub Pages when the push is a tag matching `v**` (see [Push the current `main` branch to the live site](#push-the-current-main-branch-to-the-live-site)). Deploy-time (`pages`/`id-token` write) permissions are scoped to just the `deploy` job; it never triggers on `pull_request`.
- `.github/actions/setup-hugo` — local composite action shared by both workflows above to install the Hugo CLI. Defaults to the version pinned in the root `.hugo-version` file — the same file the devcontainer's `Dockerfile` reads — so the required Hugo version only needs to be maintained in that one place.
+### FontAwesome and Bootstrap (npm, at build time)
+
+`themes/pydata` doesn't vendor FontAwesome or Bootstrap as committed files. `themes/pydata/package.json` pins the exact versions (FontAwesome's JS+SVG icon kit, Bootstrap's JS bundle); Hugo's `[[module.mounts]]` (in `themes/pydata/hugo.toml`) mounts the relevant prebuilt files straight out of `node_modules` into the asset pipeline, and `themes/pydata/layouts/_partials/head/{fontawesome,bootstrap-js}.html` load them through Hugo Pipes (fingerprinted in production builds). This means:
+
+- You need to run `npm ci` inside `themes/pydata` before `hugo build`/`hugo server` will work — the devcontainer does this automatically via `postCreateCommand`; CI does it via an `actions/setup-node` + `npm ci` step in both workflows.
+- Their license text isn't duplicated anywhere in this repo — it ships inside the respective (gitignored) npm packages under `themes/pydata/node_modules/.../LICENSE*`.
+- The Node.js version used for this is pinned in the root `.node-version` file, following the same single-source-of-truth pattern as `.hugo-version`.
+
## Credits
The `themes/pydata` theme vendored in this repository is a Hugo port of the [PyData Sphinx Theme](https://github.com/pydata/pydata-sphinx-theme) ([docs](https://pydata-sphinx-theme.readthedocs.io/en/stable/)), originally built for Sphinx documentation sites. Credit to the PyData Sphinx Theme authors and contributors for the design and functionality this port is based on.
diff --git a/themes/pydata/.gitignore b/themes/pydata/.gitignore
new file mode 100644
index 0000000..c2658d7
--- /dev/null
+++ b/themes/pydata/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/themes/pydata/hugo.toml b/themes/pydata/hugo.toml
index 45e66e7..49fe3f1 100644
--- a/themes/pydata/hugo.toml
+++ b/themes/pydata/hugo.toml
@@ -7,6 +7,41 @@ title = 'My New Hugo Project'
extended = true
min = '0.162.1'
+ # Declaring any [[module.mounts]] disables Hugo's implicit default mounts
+ # for this module, so the standard component dirs must be re-declared
+ # explicitly alongside the new npm-sourced vendor mounts below.
+ [[module.mounts]]
+ source = "content"
+ target = "content"
+ [[module.mounts]]
+ source = "static"
+ target = "static"
+ [[module.mounts]]
+ source = "layouts"
+ target = "layouts"
+ [[module.mounts]]
+ source = "data"
+ target = "data"
+ [[module.mounts]]
+ source = "assets"
+ target = "assets"
+ [[module.mounts]]
+ source = "i18n"
+ target = "i18n"
+ [[module.mounts]]
+ source = "archetypes"
+ target = "archetypes"
+
+ # Build-time-only npm deps (FontAwesome JS+SVG icon kit, Bootstrap JS
+ # bundle). Requires `npm install` in themes/pydata before
+ # `hugo build`/`hugo server`. See themes/pydata/package.json.
+ [[module.mounts]]
+ source = "node_modules/@fortawesome/fontawesome-free/js/all.min.js"
+ target = "assets/vendor/fontawesome/all.min.js"
+ [[module.mounts]]
+ source = "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
+ target = "assets/vendor/bootstrap/bootstrap.bundle.min.js"
+
# ---------------------------------------------------------------------------
# Default menus (overridable by site hugo.toml)
# ---------------------------------------------------------------------------
diff --git a/themes/pydata/layouts/_partials/head.html b/themes/pydata/layouts/_partials/head.html
index 9794d80..fec9885 100644
--- a/themes/pydata/layouts/_partials/head.html
+++ b/themes/pydata/layouts/_partials/head.html
@@ -28,7 +28,7 @@
{{- end }}
-
+{{ partial "head/fontawesome.html" . }}
{{- if not site.Params.disable_search }}
+ {{- else }}
+ {{- with . | fingerprint }}
+
+ {{- end }}
+ {{- end }}
+{{- end }}
diff --git a/themes/pydata/layouts/_partials/head/fontawesome.html b/themes/pydata/layouts/_partials/head/fontawesome.html
new file mode 100644
index 0000000..78a56bf
--- /dev/null
+++ b/themes/pydata/layouts/_partials/head/fontawesome.html
@@ -0,0 +1,15 @@
+{{- /*
+ FontAwesome's JS+SVG icon kit, mounted from node_modules via
+ [[module.mounts]] in hugo.toml (see themes/pydata/package.json). It's
+ already a prebuilt minified bundle, so no js.Build step is needed — just
+ fingerprint it in production.
+*/ -}}
+{{- with resources.Get "vendor/fontawesome/all.min.js" }}
+ {{- if hugo.IsDevelopment }}
+
+ {{- else }}
+ {{- with . | fingerprint }}
+
+ {{- end }}
+ {{- end }}
+{{- end }}
diff --git a/themes/pydata/layouts/baseof.html b/themes/pydata/layouts/baseof.html
index d343a80..30bc42e 100644
--- a/themes/pydata/layouts/baseof.html
+++ b/themes/pydata/layouts/baseof.html
@@ -63,7 +63,7 @@
{{- /* Scripts at end of body */ -}}
-
+{{ partial "head/bootstrap-js.html" . }}