Skip to content

fix(producer): local renders keep the system font the preview shows - #6592

Open
miguel-heygen wants to merge 1 commit into
mainfrom
layerbest/local-render-host-fonts
Open

miguel-heygen wants to merge 1 commit into
mainfrom
layerbest/local-render-host-fonts

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

What changes

A local render now draws a system font stack (system-ui, -apple-system, sans-serif first) in the same font the preview and snapshot show. Only cloud renders, which have no system fonts, still put Inter first. A new check warning, system_font_inter_in_cloud, says so plainly, so the author knows the cloud render will differ.

Why

compileForRender put Inter ahead of every system-primary stack on every render. That rewrite was added so distributed plans pass system-font validation, but local renders capture host fonts and the preview never got the rewrite. The same text was a different width in the preview and in the MP4.

Measured on a Linux box, 1,234,567.89 set in system-ui, -apple-system, BlinkMacSystemFont, sans-serif at 160 px:

snapshot local render
main 1039 px 937 px (Inter)
this branch 1039 px 1039 px

text-rendering: geometricPrecision is not part of the gap: the preview bundler injects the same rule, so player and render already agree on it.

How

  • htmlCompiler.ts: the Inter promotion runs only when allowSystemFontCapture === false (distributed plans and font localize set it).
  • lint/rules/fonts.ts: system_font_inter_in_cloud (warning) when a font-family in a style block starts with a system or generic family. CSS-wide keywords (inherit and so on) are not flagged. No bundled template or registry example starts a stack with a system font, so no existing project changes verdict.
  • Docs: the rule in docs/reference/lint-rules.mdx.

Tests

  • htmlCompiler.test.ts: a local compile keeps system-ui, -apple-system, sans-serif first (fails on main). The two existing promotion tests now compile with allowSystemFontCapture: false and still get Inter.
  • fonts.test.ts: the warning fires for a system stack, with its line, and stays quiet for a named primary and for inherit.
  • Mutations: promoting on every render turns the new producer test red; never promoting turns both distributed promotion tests red; dropping the lint finding or counting inherit turns the lint tests red.
  • New tests 3 runs green; lint suite 1229, CLI suite 6272 green; producer htmlCompiler, distributed/plan, render/planValidation and the deterministic-font suites green apart from one loudness test noted below.
  • End to end with the built CLI: the table above, and check prints the new warning on that project.

distributed/plan.test.ts > stitched mp4 plans > keeps assembled loudness within 0.1 LUFS fails in this run; it measures audio and does not touch fonts. Its result on the base without this change is below.

Next step (decided, not yet pushed)

The regression goldens and render --docker were rendered with Inter promoted, so this head changes 25 of the 85 regression fixtures. Decision: only a plain local render on the author's own machine uses host fonts. Distributed plans, render --docker and the regression harness all count as having no host fonts and keep Inter, so the goldens stay unchanged and --docker stays equal to the cloud render. The plan is one decision, rendersWithAuthorFonts(options, env): false for allowSystemFontCapture: false or CONTAINER=true, which both Docker images set. Tests: a container compile keeps Inter, and both Dockerfiles must keep ENV CONTAINER=true. The lint message will then name cloud and --docker renders.

@mintlify

mintlify Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Oct 27, 2026, 7:56 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES · 1 blocker · 0 important · 1 nit · e300c3c2

  • blocker: the required regression check is red, and it's this change. Shard 9 fails gsap-redraw-start-and-overlap (PSNR 24.3, 100/100 frames) and parallel-capture-regression (PSNR 28.6, 100/100 frames). Both put system-ui or sans-serif first, and their goldens were rendered in-process in Docker with Inter promoted. The other 8 shards were cancelled by fail-fast, so more goldens may fail (e.g. css-spinner-render-compat and audio-mux-parity also start with system-ui). regression is green on main. ↓ inline
  • nit: the PR body says the loudness test's "result on the base without this change is below", but nothing follows it.
Scope

Read all 5 files, plus normalizeSystemFontPrimaryFamilies/GENERIC_FAMILIES in core and every allowSystemFontCapture caller (only distributed/plan.ts and fontLocalizeCli.ts pass false). The lint rule and the compile gate look correct. CI and Windows were still running when I posted. No prior reviews.

— Genesis

const fontHtml = injectTextRenderingRule(
coalesceHeadStylesAndBodyScripts(promoteCssImportsToLinkTags(sanitizedHtml)),
);
const hostFontsMissing = options.allowSystemFontCapture === false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocker (scope): only distributed/plan.ts and font localize pass allowSystemFontCapture: false, so every in-process render stops promoting Inter, including render --docker and the producer /render server. Docker pins its own font set, so --docker output for a system-first stack moves from Inter to the image's fallback (DejaVu/Noto/Liberation), and so do the Docker-rendered regression goldens. If that's intended, regenerate the affected goldens in this PR and say in the body that --docker output changes. The lint message ("in Inter on cloud renders") then also needs to cover Docker, which matches neither the preview nor the cloud. Otherwise, keep the promotion when the render runs in the container.

@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

Agreed on the blocker. The goldens were rendered with Inter promoted, and 25 of the 85 fixtures start a font stack with a system or generic family (system-ui, sans-serif, monospace, -apple-system), so this change moves every one of them, not just the two in shard 9.

Same root, wider: render --docker would also switch those stacks from Inter to the container's fallback font. I'm settling which renders count as having the author's fonts (plain local only, or local plus Docker) before pushing. Either the harness and --docker keep Inter and the goldens stay, or all 25 goldens get regenerated in the CI image and checked one by one. Next push follows that call.

The loudness note gets the base result once that run finishes.

@github-actions

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 129 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (1)

  • seqplainkeys-none-pct-r0-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

This branch was successfully deployed

1 active deployment
staging - docs — e300c3c2 Deployed Oct 27, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant