slides: a deck names the shell's two fonts instead of embedding them - #468
Merged
Merged
Conversation
…— 86 KB off every file Measured on three real decks: the document block of a typical text deck was 80% two woff2 files, Fraunces 900 and Instrument Sans — 86 KB that every shell already carries compiled in (fontdata.ts). The bytes existed twice in every saved file; the structure an AI edits was 17–21 KB. A doc.fonts entry may now name a built-in face (asset: 'builtin:…', fonts.ts BUILTIN_FONTS) with no bytes in assets; resolveFontSrc asks the deck's table first and the shell second, and injectFonts goes through it. The starter deck names both faces. At save, adoptBuiltinFonts in slides' own facade rewrites any deck whose embedded bytes are identical to a built-in face — by bytes, never by family name, so a deck's own cut of Fraunces is kept — and the bytes leave the file; the live document is never touched. An older shell renders those two families in the system fallback until it updates: a degrade, stated in the model and in DECISIONS, accepted for the saving. Measured in Chrome against the built shell: both faces load from the shell (document.fonts), the starter deck saves with no font bytes, and a legacy deck carrying the old keys saves 85,269 bytes smaller with the live document untouched. scripts/test-slides-fonts.ts (25, registered) pins resolution, adoption by bytes, idempotence, the facade wiring and the measured saving. Changelog and DECISIONS entries ride along.
Build size
Updated: |
A fonts[].asset of the form builtin:… names a face the shell carries; the validator reported it as a missing asset (2 errors on the starter deck, caught by the validation rig in CI). A known built-in name is now a satisfied reference; an unknown built-in name is the error, as is an asset key with no bytes. Cases in test-validate (48).
nyblnet
added a commit
that referenced
this pull request
Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Measured first, on three real decks' document blocks: a typical text deck was 80% two woff2 files — Fraunces 900 and Instrument Sans, 86 KB — which every shell already carries compiled in (
fontdata.ts). The bytes existed twice in every saved file. The structure an AI actually edits was 17–21 KB.Change. A
doc.fonts[]entry may name a built-in face (asset: 'builtin:fraunces-900'/'builtin:instrument-sans',fonts.ts BUILTIN_FONTS) with no bytes inassets.resolveFontSrcasks the deck's table first, then the shell;injectFontsgoes through it. The starter deck names both. At save,adoptBuiltinFonts(slides' facade, beside the asset prune) rewrites any deck whose embedded bytes are identical to a built-in face — by bytes, never by family name, so a deck's own cut of Fraunces is kept — and the bytes leave the file. The live document is never touched.The trade, stated: an older shell opening a new deck renders those two families in the system fallback until it updates itself — a degrade, not a break. Accepted for the saving; in the model comment and a DECISIONS entry.
Measured in Chrome against the built shell: both faces load from the shell (
document.fonts.checktrue, status loaded); the starter deck saves with zero font bytes; a legacy deck carrying the old keys saves 85,269 bytes smaller with the live document untouched.scripts/test-slides-fonts.ts(25 checks, registered): resolution, adoption by bytes and not by name, idempotence, other assets untouched, the facade wiring, and the measured saving. Also green: typecheck, build:single + splice gate, slides-assets 28, export-secrets 74, ci-registered 318, i18n, modelkeys. Changelog entry under[Unreleased](tail; one-line rebase if it lands after #463/#465). No CLAUDE.md/AGENTS.md change.Not in here, next lever: photos have no downscale or recompression at insert.