Self-hosted stylesheet assets are referenced with an absolute /myst_assets_folder/… URL, which does not exist in myst build --html output. Every KaTeX font file 404s on statically built sites — the deployment mode the lectures actually use.
What happens
Remix rewrites url() in a bundled stylesheet to ${publicPath}_assets/<file>, and publicPath is /myst_assets_folder/ (remix.config.prod.js:8). So the KaTeX stylesheet self-hosted in #125 ships with 60 absolute references:
url(/myst_assets_folder/_assets/KaTeX_AMS-Regular-U6PRYMIZ.woff2)
Under myst start that resolves, because template/server.js:21 mounts express.static('public/build') at exactly that path. A static build has no such route, and mystmd's asset rewriter only rewrites .html, .js and .json — never .css — so the path inside the stylesheet is left pointing at a directory the output does not contain.
Reproduction
myst build --html of the repo's own visual fixture against a current make build-theme:
| check |
result |
<link> to the KaTeX stylesheet in the HTML |
rewritten to /build/_assets/katex.min-STXY5V2I.css — loads |
url() inside that stylesheet |
still /myst_assets_folder/_assets/KaTeX_AMS-Regular-U6PRYMIZ.woff2 |
myst_assets_folder/ in the output tree |
absent |
| where the fonts actually landed |
build/_assets/ — 20 woff2 files |
So the stylesheet loads and every font it asks for 404s. KaTeX then falls back to system fonts for maths glyphs, which is the degraded rendering #125 set out to prevent — now on every static site rather than only where jsdelivr is blocked.
Scope
Only the KaTeX stylesheet is affected today: app.css and thebe-core.css emit no url() references (checked — 0 matches each). The exposure arrived with #125; before that, KaTeX came from jsdelivr with absolute CDN font URLs that resolved everywhere jsdelivr was reachable.
This also blocks #131: self-hosting Source Sans 3 through the same app/links.ts route would put body text on the same broken path, and it would fail silently in exactly the same way.
Suggested direction
Make the emitted URLs relative to the stylesheet (url(./KaTeX_AMS-Regular-U6PRYMIZ.woff2)). The CSS and its font files are emitted into the same _assets/ directory in both layouts, so a relative reference resolves in myst start (/myst_assets_folder/_assets/…), in a static build (/build/_assets/…), and under a baseurl — where today's absolute path is wrong as well. publicPath itself cannot be made relative, since Remix also uses it to load JS chunks, so a post-build rewrite of the emitted CSS is the smallest change that covers every mode.
Worth proposing upstream separately that mystmd's static rewriter should treat .css like .html/.js/.json — but that only helps once consumers upgrade the CLI, so the theme should not depend on it.
Self-hosted stylesheet assets are referenced with an absolute
/myst_assets_folder/…URL, which does not exist inmyst build --htmloutput. Every KaTeX font file 404s on statically built sites — the deployment mode the lectures actually use.What happens
Remix rewrites
url()in a bundled stylesheet to${publicPath}_assets/<file>, andpublicPathis/myst_assets_folder/(remix.config.prod.js:8). So the KaTeX stylesheet self-hosted in #125 ships with 60 absolute references:Under
myst startthat resolves, becausetemplate/server.js:21mountsexpress.static('public/build')at exactly that path. A static build has no such route, and mystmd's asset rewriter only rewrites.html,.jsand.json— never.css— so the path inside the stylesheet is left pointing at a directory the output does not contain.Reproduction
myst build --htmlof the repo's own visual fixture against a currentmake build-theme:<link>to the KaTeX stylesheet in the HTML/build/_assets/katex.min-STXY5V2I.css— loadsurl()inside that stylesheet/myst_assets_folder/_assets/KaTeX_AMS-Regular-U6PRYMIZ.woff2myst_assets_folder/in the output treebuild/_assets/— 20 woff2 filesSo the stylesheet loads and every font it asks for 404s. KaTeX then falls back to system fonts for maths glyphs, which is the degraded rendering #125 set out to prevent — now on every static site rather than only where jsdelivr is blocked.
Scope
Only the KaTeX stylesheet is affected today:
app.cssandthebe-core.cssemit nourl()references (checked — 0 matches each). The exposure arrived with #125; before that, KaTeX came from jsdelivr with absolute CDN font URLs that resolved everywhere jsdelivr was reachable.This also blocks #131: self-hosting Source Sans 3 through the same
app/links.tsroute would put body text on the same broken path, and it would fail silently in exactly the same way.Suggested direction
Make the emitted URLs relative to the stylesheet (
url(./KaTeX_AMS-Regular-U6PRYMIZ.woff2)). The CSS and its font files are emitted into the same_assets/directory in both layouts, so a relative reference resolves inmyst start(/myst_assets_folder/_assets/…), in a static build (/build/_assets/…), and under abaseurl— where today's absolute path is wrong as well.publicPathitself cannot be made relative, since Remix also uses it to load JS chunks, so a post-build rewrite of the emitted CSS is the smallest change that covers every mode.Worth proposing upstream separately that mystmd's static rewriter should treat
.csslike.html/.js/.json— but that only helps once consumers upgrade the CLI, so the theme should not depend on it.