Skip to content

Commit e91c5ad

Browse files
committed
fixup: add myst theme
1 parent cf5b871 commit e91c5ad

1 file changed

Lines changed: 62 additions & 115 deletions

File tree

docs/decisions/0001-myst-migration/0009-myst-theme-integration.md

Lines changed: 62 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -7,134 +7,81 @@ Branch: lb/myst-migration
77
## Context
88

99
`scientific-python/scientific-python-myst-theme` provides shared MyST styling,
10-
config, plugins (`team-grid.mjs`), assets (logo, favicon, CSS), and footer
11-
template for Scientific Python MyST sites. It is distributed as a **copier
12-
template**, not a pip or npm package. The intended consumption pattern is for
13-
a site's `myst.yml` to `extends:` a `config/scientific-python.yml` file that
14-
ships in the template.
15-
16-
The theme is brand-new (created 2026-05-18, 0 tagged releases, 5 forks as of
17-
2026-05-19). The upstream HEAD on `main` is currently the only available
18-
pinning target.
19-
20-
This site already uses one git submodule (`external-content/cookie`, Jekyll,
21-
pinned to `2025.10.01`, see ADR 0004). We need a strategy for pulling theme
22-
files into `content/` that is reproducible on Netlify CI (`make html-all`),
23-
on a fresh `git clone` + `myst start`, and across maintainer machines, while
24-
allowing the theme to evolve upstream.
25-
26-
Constraint: MyST resolves paths in `myst.yml` (including `extends:`, `style:`,
27-
`logo:`, plugins) relative to the `myst.yml` location, which is `content/`.
28-
Theme files must end up at predictable paths under `content/`.
10+
config, plugins (`team-grid.mjs`), assets (logo, favicon, CSS), and a footer
11+
template. It is distributed as a **copier template**, not a pip/npm package: the
12+
intended consumption pattern is for a site's `myst.yml` to `extends:` a
13+
`config/scientific-python.yml` shipped in the template.
14+
15+
The theme is brand-new (created 2026-05-18, 0 tagged releases), so upstream
16+
`main` HEAD is the only pinning target. We need a strategy for pulling theme
17+
files into `content/` that is reproducible on Netlify CI (`make html-all`), on a
18+
fresh `git clone` + `myst start`, and across maintainer machines.
19+
20+
Constraint: MyST resolves `myst.yml` paths (`extends:`, `style:`, `logo:`,
21+
plugins) relative to the `myst.yml` location, which is `content/`. Theme files
22+
must land at predictable paths under `content/`.
2923

3024
## Decision
3125

32-
Adopt **committed theme files, vendored selectively from a copier render**
33-
(a refinement of Option 2).
26+
Adopt **committed theme files, vendored selectively from a copier render** (a
27+
refinement of Option 2).
3428

35-
The upstream template is a _scaffold-a-new-site_ template: a full
36-
`copier copy` renders `index.md`, `myst.yml`, `about.md`, `news.md`,
37-
`Makefile`, and `.gitignore` alongside the theme infrastructure. Our
38-
`content/` already holds a populated site, so a direct
39-
`copier copy ... content/` would clobber `index.md`/`myst.yml` and add
40-
unwanted pages. Therefore we render to a throwaway directory and copy in only
41-
the theme-infrastructure files.
29+
Upstream is a _scaffold-a-new-site_ template: a full `copier copy` renders
30+
`index.md`, `myst.yml`, `about.md`, `news.md`, `Makefile`, `.gitignore`
31+
alongside the theme infrastructure. Our `content/` already holds a populated
32+
site, so a direct copy would clobber `index.md`/`myst.yml` and add unwanted
33+
pages. We therefore render to a throwaway dir and copy in only the theme files.
4234

4335
Implementation (as performed):
4436

45-
- Render once to a temp dir:
46-
`pixi exec --spec copier copier copy --trust --defaults gh:scientific-python/scientific-python-myst-theme <tmp>`.
47-
(`copier` is run ephemerally via `pixi exec`; it is not a project
48-
dependency.)
49-
- Vendor only these files into `content/`, committed to the repo:
50-
`config/scientific-python.yml`, `assets/css/scientific-python.css`,
51-
`assets/images/logo.svg`, `assets/images/favicon.ico`, `team-grid.mjs`,
52-
`footer.md`, and `.copier-answers.yml` (kept for provenance: it records
53-
the upstream `_commit`).
54-
- Add `extends: config/scientific-python.yml` to `content/myst.yml`. The
55-
extended config provides `site.template`, `folders`, and the `hide_*`
56-
options. `site.options.style` must be respecified locally because `extends`
57-
overrides (does not append) it: it is set to a list of the theme CSS plus a
58-
local `assets/css/custom.css` override (the former top-level `custom.css`,
59-
relocated under `content/assets/css/`).
60-
- The previously duplicated top-level `assets/` (logo and favicon, byte
61-
identical to the theme copies) is removed; `content/assets/` is now the
62-
single source.
63-
- Do not add copier to the Netlify build command or to `make prepare`. CI
64-
consumes the committed files as-is.
65-
66-
Update path: because our `index.md`/`myst.yml` have diverged from the
67-
template, `copier update` cannot be run cleanly against `content/` (it would
68-
conflict on the scaffold files). Updates are instead done by re-rendering to a
69-
temp dir and diffing the vendored files by hand. Revisit Option 3 (scheduled
70-
GitHub Action) and a cleaner `copier update` flow once the upstream theme
71-
separates "theme core" from "site scaffold" and cuts tagged releases.
37+
- Render once to a temp dir via `pixi exec --spec copier copier copy --trust
38+
--defaults gh:scientific-python/scientific-python-myst-theme <tmp>` (copier is
39+
run ephemerally; it is not a project dependency).
40+
- Vendor only these into `content/`, committed: `config/scientific-python.yml`,
41+
`assets/css/scientific-python.css`, `assets/images/logo.svg`,
42+
`assets/images/favicon.ico`, `team-grid.mjs`, `footer.md`, and
43+
`.copier-answers.yml` (provenance: records upstream `_commit`).
44+
- Add `extends: config/scientific-python.yml` to `content/myst.yml`. `style`
45+
must be respecified locally — `extends` overrides (does not append) it — as a
46+
list of theme CSS plus a local `assets/css/custom.css` override.
47+
- Remove the previously duplicated top-level `assets/` (logo/favicon byte
48+
identical to theme copies); `content/assets/` is now the single source.
49+
- Do not add copier to the Netlify build or `make prepare`; CI consumes the
50+
committed files as-is.
51+
52+
Update path: `copier update` cannot run cleanly (it conflicts on the diverged
53+
scaffold files), so updates are done by re-rendering to a temp dir and diffing
54+
the vendored files by hand. Revisit Option 3 once upstream separates "theme
55+
core" from "site scaffold" and cuts tagged releases.
7256

7357
Known upstream gap: `config/scientific-python.yml` sets
74-
`site.parts.primary_sidebar_footer: sidebar-footer.md`, but the template ships
75-
no such file. The build emits a non-fatal warning
76-
(`Part file does not exist: sidebar-footer.md`). Tracked to be raised with the
77-
theme maintainer separately; not stubbed locally.
58+
`primary_sidebar_footer: sidebar-footer.md`, which the template does not ship; the
59+
build emits a non-fatal warning. To be raised upstream, not stubbed.
7860

79-
`external-content/cookie` is unaffected and remains a git submodule per
80-
ADR 0004. The two integrations differ in kind: cookie is a separately-built
81-
Jekyll site whose output is overlaid on `public/development/`; the theme is
82-
config plus static assets consumed by the MyST build itself.
61+
`external-content/cookie` is unaffected (ADR 0004): it is a separately-built
62+
Jekyll site overlaid on `public/development/`, whereas the theme is config plus
63+
assets consumed by the MyST build itself.
8364

8465
## Options considered
8566

86-
1. **Git submodule** (mirror cookie pattern) — add
87-
`external-content/scientific-python-myst-theme`, have `make prepare` copy
88-
files into `content/`. Consistent with cookie, but introduces transient
89-
copied files, dual source of truth (submodule + working copy), and forces
90-
a copy step into every fresh `myst start`. Also: the theme is a copier
91-
template, not a runnable artifact, so cloning the source repo as a
92-
submodule is a structural mismatch.
93-
2. **Copier copy, committed files**`copier copy` once, commit rendered
94-
files, maintainers run `copier update` manually. Files in the repo,
95-
zero new build-time deps, `myst start` works on fresh clone. Tradeoff:
96-
manual update cadence; theme drift possible if maintainers neglect updates.
97-
3. **Scheduled GitHub Action + copier update** — cron-triggered workflow runs
98-
`copier update --defaults` and opens a PR on diff. Automatic; files still
99-
committed. Adds a workflow file and a maintenance surface (handling
100-
merge conflicts in auto-PRs). Premature while upstream has no releases.
101-
4. **Pre-commit hook running copier update** — slows every commit, doesn't
102-
help CI on a fresh checkout, and surprises contributors who don't have
103-
copier installed. Rejected.
104-
5. **Rethink cookie integration** — cookie is a separately-built Jekyll site
105-
with its own Ruby toolchain, release tags, and an independent contributor
106-
community. Submodule + Makefile remains the right shape for it. The
107-
theme decision does not alter ADR 0004.
67+
1. **Git submodule** (mirror cookie) — introduces transient copied files, dual
68+
source of truth, and a copy step on every `myst start`; a copier template is
69+
not a runnable artifact, so a source submodule is a structural mismatch.
70+
2. **Copier copy, committed files** (chosen) — zero new build-time deps,
71+
`myst start` works on fresh clone. Tradeoff: manual update cadence, drift risk.
72+
3. **Scheduled GitHub Action + copier update** — cron PR on diff; automatic but
73+
adds a workflow and auto-PR conflict maintenance. Premature with no releases.
74+
4. **Pre-commit hook running copier update** — slows every commit, doesn't help
75+
CI on fresh checkout, surprises contributors without copier. Rejected.
76+
5. **Rethink cookie integration** — cookie's Ruby toolchain and release tags keep
77+
submodule + Makefile right for it; this decision does not alter ADR 0004.
10878

10979
## Consequences
11080

111-
- `content/config/scientific-python.yml`,
112-
`content/assets/css/scientific-python.css`,
113-
`content/assets/css/custom.css`, `content/assets/images/logo.svg`,
114-
`content/assets/images/favicon.ico`, `content/team-grid.mjs`,
115-
`content/footer.md`, and `content/.copier-answers.yml` are committed to the
116-
repo.
117-
- `content/myst.yml` gains `extends: config/scientific-python.yml`, points
118-
`logo`/`favicon` at the content-local theme assets, and respecifies `style`
119-
as a list (theme CSS plus local `custom.css`).
120-
- The former top-level `assets/` directory is removed: its `logo.svg` and
121-
`favicon.ico` were byte identical to the theme copies, and its unused
122-
`custom.css` Lato override was relocated to `content/assets/css/custom.css`
123-
and wired into `myst.yml`.
124-
- Netlify config (`netlify.toml`) is unchanged. `make prepare` is unchanged.
125-
`make html-all` continues to work because all theme files are already on
126-
disk after `git clone`.
127-
- Fresh clone developer experience: `git clone && cd content && myst start`
128-
works with no extra setup beyond mystmd itself.
129-
- The committed build path is the `Makefile` (`make html` / `make html-all`,
130-
used by Netlify), which already runs the build inside `content/`. The
131-
`pixi.toml` `build`/`serve` tasks are a local-only convenience (`pixi.toml`
132-
is in `.git/info/exclude`); they were fixed to run with `cwd = content` so
133-
they work from the repo root.
134-
- Theme updates are manual (re-render and diff). Risk: drift from upstream.
135-
Mitigation: revisit Option 3 once upstream separates theme core from site
136-
scaffold and cuts a tagged release.
137-
- The lack of upstream tags is recorded here; when the theme publishes its
138-
first release, pin `.copier-answers.yml` to that tag.
139-
- A non-fatal `sidebar-footer.md` warning remains pending an upstream fix.
140-
- Cookie submodule strategy (ADR 0004) is unaffected.
81+
- `netlify.toml` and `make prepare` are unchanged; `make html-all` (the
82+
Netlify build path) works because all theme files are on disk after `git
83+
clone`. Fresh clone `git clone && cd content && myst start` needs no setup.
84+
- `pixi.toml` `build`/`serve` tasks (local-only, git-excluded) were fixed to run
85+
with `cwd = content`.
86+
- Manual updates risk upstream drift; pin `.copier-answers.yml` to the first
87+
tagged release when available, and revisit Option 3 then.

0 commit comments

Comments
 (0)