Skip to content

feat(sketch): deploy-time flag to prune 13MB CJK canvas font - #9088

Merged
bolichen97 merged 1 commit into
mainfrom
fix/sketch-cjk-font-deploy-flag-8091
Sep 7, 2026
Merged

feat(sketch): deploy-time flag to prune 13MB CJK canvas font#9088
bolichen97 merged 1 commit into
mainfrom
fix/sketch-cjk-font-deploy-flag-8091

Conversation

@chenmingwei23

Copy link
Copy Markdown
Contributor

What is the problem?

The sketch pad (#8041) self-hosts Excalidraw's canvas fonts so no CDN is contacted, emitting them at build time via excalidrawFontsPlugin() in website/vite.config.ts. Measured at main 31cd87f2 (package pin @excalidraw/excalidraw@0.18.1): the plugin emits 13,107,068 bytes across 234 files with no filter, of which the Xiaolai CJK handwriting family is 12,667,492 bytes across 209 files -- 96.6% of the payload. Every other family combined is 0.44 MB. A size-sensitive deployment has no way to opt out of the 12.67 MB CJK family.

Why this matters to the user

Two different users are in tension. A zh/ja/ko user needs Xiaolai to sketch with hand-drawn CJK text; without it Excalidraw substitutes a system font, losing the hand-drawn style. A deployer building a size-sensitive image wants the 12.67 MB gone. Today only the first is served, and there is no lever for the second.

How the fix solves it

A single build-time env var, KIROCREW_PRUNE_SKETCH_CJK_FONT, gates a filename filter over the families the plugin already enumerates -- no new configuration layer, no new dependency, one file.

  • Chain from symptom to root cause: the size cost is 96.6% one family (symptom) -> the plugin emits every family unconditionally with no seam to exclude one (root cause) -> add a default-off predicate that drops the named family from both the build emit and the dev-server route.
  • The default is unset, which ships every family exactly as before. No existing build changes and no CJK user is degraded unless a deployer deliberately sets the variable.
  • It does NOT silently drop CJK. When engaged, the plugin prints a loud build-time warning naming the pruned family, its size, and the fallback consequence. That is a line of build output, not a runtime UI surface.
  • The existing edition seam (editionExtensionPlugin, KIROCREW_EDITION_DIR/KIROCREW_ALLOW_EDITION) handles branding and asset overlays but has no font hook, so a new KIROCREW_* var in the same family is the minimal addition.

Still needing a human, and deliberately NOT decided here: what a pruned build should show CJK users at runtime (accept silent system fallback, or surface a notice). Defaulting the flag off decouples that product-policy call from this reversible build option. This re-triage was routed to needs-human by dwu96 (2026-09-03T20:37Z), whose read that "neither branch is derivable from the measurement" still holds -- this PR ships only the reversible, default-off half.

What tests we did

Verified by real vite build runs in the worktree against the installed 0.18.1 package (full npm run build was not runnable here: its tsc -b step fails on missing @storybook/react-vite stubs in the borrowed node_modules, all errors under src/stories/, none in vite.config.ts; ran vite build directly):

  • Flag unset (default): 234 font files emitted, 209 Xiaolai -- identical to today.
  • KIROCREW_PRUNE_SKETCH_CJK_FONT=1: 25 font files emitted (234 minus Xiaolai's 209), 0 Xiaolai, 8 other families intact, and the build-time warning fired once.

Other suggestions

The open runtime-signal question above is worth its own issue once a maintainer picks the acceptable-degradation bar; it is not blocked by this flag.

Pattern harvest

Rule candidate: when an asset-emitting build plugin enumerates a set (fonts, locales, vendored files), a deployment-time prune is a filename filter over what it already lists plus a loud build-time warning, defaulted off -- not a new config layer. This keeps the size lever reversible and the policy question (what the pruned build shows the user) separable from the code.

Refs #8091

@chenmingwei23
chenmingwei23 requested a review from a team as a code owner September 6, 2026 18:40
@github-actions github-actions Bot added the readiness: checking Automated validation is still running label Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

UX Review (Fable 5) — ✅ PASS

UX-level review of 7d882aef72b7fa172dafb7b6999a6896582d8960 — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

This PR changes only website/vite.config.ts — a default-off build-time env flag with a deployer-facing console warning. It adds or changes no user-visible control, string, or rendered surface, so the absent blind read and screenshots leave no evidence gap. The one end-user consequence (system-font fallback for CJK sketch text) occurs only when a deployer explicitly opts in past a loud warning that names the consequence and the reversal, and the runtime-notice question is explicitly deferred to a human on the issue.

UX-Verdict: PASS

Build-config-only change with no user-visible surface; the deployer-facing warning names what happened, the consequence, and the undo.

[UX-REVIEWED] 7d882ae

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Opus 4.8 Review — ✅ no blocking findings

Reviewed 7d882aef72b7fa172dafb7b6999a6896582d8960 — this comment is updated in place on each push.

Review details

No findings.

[OPUS-REVIEWED] 7d882ae

Verdict parsed from the review's SHA-scoped output markers for commit 7d882aef72b7fa172dafb7b6999a6896582d8960.

False positive or not applicable? A repository writer can comment:
/ai-review override fable 7d882aef72b7fa172dafb7b6999a6896582d8960: <one-sentence reason>

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Design Review (Fable 5) — ✅ PASS

Design-level review of 7d882aef72b7fa172dafb7b6999a6896582d8960 — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

Both candidate findings are checked. Final review:

Design-Verdict: PASS

Measured, default-off, one-file filter over an existing enumeration — the proportionate shape for a deploy-time size lever, with dev/build parity handled.

Suggestions

  • The warning hardcodes the family, count, and "~12.67 MB" from a measurement of 0.18.1; derive them from what listFonts() actually skipped (and complain if the Xiaolai dir is absent), otherwise a package upgrade that renames the family leaves the flag silently inert while the warning still claims the prune happened.
  • The flag lives only in a vite.config.ts comment and the issue; add a line to website/docs/extension-seams.md, which already catalogs the build-time KIROCREW_* seams, so the size-sensitive deployer this PR serves can actually find the lever.

[DESIGN-REVIEWED] 7d882ae

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

GPT 5.6 Review — ✅ no blocking findings

GPT 5.6 completed its review of 7d882aef72b7fa172dafb7b6999a6896582d8960 and found no blocking issues.

This comment is updated in place on each push.

Review details

No findings.
[GPT-REVIEWED] 7d882ae

False positive or not applicable? A repository writer can comment:
/ai-review override gpt 7d882aef72b7fa172dafb7b6999a6896582d8960: <one-sentence reason>

@github-actions github-actions Bot added readiness: passed Eligible automated validation passed for the current revision and removed readiness: checking Automated validation is still running labels Sep 6, 2026

@bolichen97 bolichen97 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Tech Lead review — approved.

Default is opt-in, verified. const pruneCjk = process.env.KIROCREW_PRUNE_SKETCH_CJK_FONT === '1' is a strict equality against '1', so unset / empty / 0 / true all evaluate false and isPruned() short-circuits before the family lookup. listFonts() therefore emits all 234 files exactly as today, and the dev-server route serves all of them. No existing build changes and no zh/ja/ko user loses the Xiaolai hand-drawn family unless a deployer deliberately sets the variable.

No i18n interaction. The pruned asset is an Excalidraw canvas font served from dist/vendor/excalidraw/fonts/**. It is not part of the dashboard's 12-locale i18n path — no locale catalog, no t() key, no dashboard typography stack references it — so dashboard CJK text rendering across all 12 languages is untouched in both flag states. The only consequence, and only under an explicit opt-in, is that sketch-canvas CJK text falls back to a system font: style loss, not legibility loss.

Failure mode is fail-safe. If a future @excalidraw/excalidraw upgrade renames the family, PRUNABLE_CJK_FONT_FAMILIES stops matching and the build ships every font — i.e. the flag goes inert in the direction that keeps CJK users whole, never in the direction that breaks them.

Scope and signals. One file, +40/-1, no new dependency and no new configuration layer — a filename predicate over the enumeration the plugin already walks, plus dev/build parity via the same isPruned(). All 5 AI review lanes clean on 7d882ae (GPT no findings, Opus no findings, UX PASS, Design PASS, First Principles success), PR Readiness success, no unresolved review threads, readiness: passed postdates the head commit.

Design Review's two suggestions are advisory and I am not blocking on them: deriving the warning's family/size from what listFonts() actually skipped instead of the hardcoded ~12.67 MB, and cataloging the flag in website/docs/extension-seams.md alongside the other build-time KIROCREW_* seams. The second is the one that matters for discoverability — worth a follow-up so the size-sensitive deployer this PR serves can find the lever. The runtime-notice product question stays deferred on #8091, correctly, since a default-off reversible build flag does not force that call.

@bolichen97
bolichen97 merged commit 84a4f4b into main Sep 7, 2026
64 checks passed
@bolichen97
bolichen97 deleted the fix/sketch-cjk-font-deploy-flag-8091 branch September 7, 2026 10:16
@github-actions github-actions Bot removed the readiness: passed Eligible automated validation passed for the current revision label Sep 7, 2026
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.

2 participants