Background
The Build and Deploy Pages workflow was failing repeatedly, always in the deploy job's deploy-pages step at syncing_files / deployment_queued (Deployment failed, try again later. / Timeout reached, aborting!). The Continuous Integration (lint/test) workflow was unaffected, and githubstatus.com showed no platform incident during the failure windows. Root cause: the ./public artifact had grown large (~755 MB, ~15k files), and syncing_files scales with the raw unpacked size and file count.
Deleting the largest frozen snapshots already restored a green deploy:
- Removed
public/old/a20 + a21 (~203 MB, ~4.8k files) and their nav links.
- Removed
v1.4/v2.6 source maps (~7.6 MB).
This issue tracks the remaining levers so we can act quickly if the deploy gets flaky again.
How GitHub Pages deploy actually compresses (important)
upload-pages-artifact@v4 builds an uncompressed tar, then upload-artifact (zip/deflate, level 6) compresses it. So the uploaded artifact is already deflated — pre-compressing text files does not shrink the upload.
- The step that fails,
syncing_files, operates on the unpacked raw files pushed to the Pages host. It scales with total raw bytes and file count, independent of the zip. So the effective levers are "make the unpacked tree smaller / fewer files".
- Committing a compressed form (gzip/minify/index) defeats git delta compression (blob bloat), breaks review, and bloats pushes. Prefer compressing in a CI build step (like
build:ts already does for JS), keeping the committed source human-readable.
Remaining size-reduction options (measured)
1. Prefab pages: static shell + client-rendered block table (recommended, ~-45 MB)
public/prefabs/*.html is 1866 files / 49.7 MB, of which the block table is 86% (45 MB). That table duplicates data already present in prefab-block-counts.json (9.3 MB) and labels/{lang}/blocks.json.
Keep the 1866 pages at the same URLs (SEO, direct links, no-JS metadata preserved via the 7.1 MB shell), drop only the block table from the HTML, and render it client-side in main.js from the existing prefab-block-counts.json + labels dict. Reusing the existing JSON means no new files, unchanged file count, ~-45 MB, and block labels gain i18n support.
- Link generators to update:
public/prefabs.js:599, src/index/prefab-inspector-handler.ts:156, and the reverse HREF_PATTERN at public/prefabs.js:481.
- Note:
prefab-block-counts.json excludes the air block; decide whether to show/drop it.
- Lighter-touch fallback (keeps full no-JS): just emit a more compact static block table (drop
class="block", drop the duplicated label column) for ~-20 MB.
2. Index-encode prefab-block-counts.json
Block names (12,842 unique, referenced 296,539 times) → dictionary + integer indices: raw 9.3 → 3.3 MB (-65%), gzip 1.46 → 0.85 MB. Requires a loader change. Do the encoding as a CI transform so the committed file stays pretty-printed and stable.
3. Drop source maps from the production build
tools/build.ts prodOpts uses sourcemap: "external", so .js.map files ship in the artifact. Setting sourcemap: false removes ~3-4 MB with no runtime impact.
Not worth it
- JSON minify: ~-7% only (tab-indented, whitespace is ~12%).
- JPEG quality reduction: already 280×210 @ q75; ~-2.5–5 MB with visible degradation.
- HTML can't be pre-gzipped (Pages does not add
Content-Encoding); .gz/.jpg are already compressed.
Status
Deploy is currently green after the snapshot deletions, so the above are follow-up optimizations, prioritized by impact: #1 (prefab hybrid) is the single biggest lever.
Background
The Build and Deploy Pages workflow was failing repeatedly, always in the
deployjob'sdeploy-pagesstep atsyncing_files/deployment_queued(Deployment failed, try again later./Timeout reached, aborting!). TheContinuous Integration(lint/test) workflow was unaffected, and githubstatus.com showed no platform incident during the failure windows. Root cause: the./publicartifact had grown large (~755 MB, ~15k files), andsyncing_filesscales with the raw unpacked size and file count.Deleting the largest frozen snapshots already restored a green deploy:
public/old/a20+a21(~203 MB, ~4.8k files) and their nav links.v1.4/v2.6source maps (~7.6 MB).This issue tracks the remaining levers so we can act quickly if the deploy gets flaky again.
How GitHub Pages deploy actually compresses (important)
upload-pages-artifact@v4builds an uncompressed tar, thenupload-artifact(zip/deflate, level 6) compresses it. So the uploaded artifact is already deflated — pre-compressing text files does not shrink the upload.syncing_files, operates on the unpacked raw files pushed to the Pages host. It scales with total raw bytes and file count, independent of the zip. So the effective levers are "make the unpacked tree smaller / fewer files".build:tsalready does for JS), keeping the committed source human-readable.Remaining size-reduction options (measured)
1. Prefab pages: static shell + client-rendered block table (recommended, ~-45 MB)
public/prefabs/*.htmlis 1866 files / 49.7 MB, of which the block table is 86% (45 MB). That table duplicates data already present inprefab-block-counts.json(9.3 MB) andlabels/{lang}/blocks.json.Keep the 1866 pages at the same URLs (SEO, direct links, no-JS metadata preserved via the 7.1 MB shell), drop only the block table from the HTML, and render it client-side in
main.jsfrom the existingprefab-block-counts.json+ labels dict. Reusing the existing JSON means no new files, unchanged file count, ~-45 MB, and block labels gain i18n support.public/prefabs.js:599,src/index/prefab-inspector-handler.ts:156, and the reverseHREF_PATTERNatpublic/prefabs.js:481.prefab-block-counts.jsonexcludes theairblock; decide whether to show/drop it.class="block", drop the duplicated label column) for ~-20 MB.2. Index-encode
prefab-block-counts.jsonBlock names (12,842 unique, referenced 296,539 times) → dictionary + integer indices: raw 9.3 → 3.3 MB (-65%), gzip 1.46 → 0.85 MB. Requires a loader change. Do the encoding as a CI transform so the committed file stays pretty-printed and stable.
3. Drop source maps from the production build
tools/build.tsprodOptsusessourcemap: "external", so.js.mapfiles ship in the artifact. Settingsourcemap: falseremoves ~3-4 MB with no runtime impact.Not worth it
Content-Encoding);.gz/.jpgare already compressed.Status
Deploy is currently green after the snapshot deletions, so the above are follow-up optimizations, prioritized by impact: #1 (prefab hybrid) is the single biggest lever.