Unblocked and re-dispatched 2026-09-04T14:25Z on the maintainer's go-ahead. The Blocked-by: #265 is lifted: #265's investigation is permitted inside this card if diagnosis needs it (see below), rather than forcing a separate round. The verification layer from #269 is now live, so a bad deploy is detected in about a minute and rolled back.
Current state
The site is up and serving Worker version 69c79ee3-… (2026-08-25). It is stale: everything merged since then is on main and not published.
Deploys are rejected. deploy-docs.yml builds a Worker over Cloudflare's 64 MiB uncompressed limit; the upload is refused at version creation with code: 10027. A rejected upload creates no version, so the good version keeps serving. As of #269 that failure is no longer silent — it files and updates #272.
The defect
fumadocs-mdx imports every page eagerly, so all seven locales' compiled corpus is inlined into every server entrypoint that touches source — the docs page, /llms.txt, /llms-full.txt, /llms.mdx/*, /og/*, /api/search, /sitemap.xml — and the bundler then inlined that set five times over.
The content is not the weight. All 397 .mdx files total 2.50 MiB; handler.mjs measured ~110 MiB. A probe sentence occurring once in one English page appeared 15 times in the bundle. A 40x bundling multiplier is the weight. ⛔ A fix that deletes documentation to fit is the wrong fix.
The margin was never healthy. Run #105, the last good deploy, logged Total Upload: 62747.87 KiB — 95.7% of the limit. The commit that crossed it (c243ad79) was 15 lines and made its own output smaller. Anything landing that week would have done it.
⛔ What the previous attempt got right, and the one thing nobody knows
PR #263 set async: true on the docs collection: handler.mjs 100.93 → 48.47 MiB locally, 58541 KiB (89.3%) measured in CI. It was ablation-verified under real workerd — breaking a lazy thunk took /api/search from 200/22890 B to 500/0 B and a byte-identical restore brought it back.
It was merged, the upload was accepted, and the site broke. Rolled back within ~20 minutes, then reverted (PR #268).
Nobody diagnosed why it broke rendering. That is the open question and it is the first deliverable here — not the fix. The diagnosis was right about the cause of the size; what it did to the render path was never established, only observed.
⛔ Do not re-apply PR #263's diff and hope. If async: true turns out to be the right shape after all, it has to arrive with an explanation of why it broke rendering last time and what makes it safe now.
Verification, and what changed since the last attempt
Since #269 / PR #270 landed, every deploy is followed by a smoke check of the live site (4 pages, 12 structural rules, a negative control every run proving it can fail), a bad deploy auto-dispatches a rollback, and any failure files a card.
⚠️ That net is a backstop, not the verification. The chain deploy succeeds → smoke fails → rollback fires has never executed, because no deploy has succeeded since the layer landed. Relying on it as the primary check would be this morning's mistake wearing better clothes.
#265's investigation is in scope here if you need it. Docs page routes 404 under local wrangler dev / opennextjs-cloudflare preview — on main too, so it is pre-existing. If making that work is what it takes to see a page render before merge, do it and say so; that is a better outcome than shipping on the backstop. If it turns into a rabbit hole, stop and report rather than sinking the round into it.
Acceptance
- A green
Deploy Docs with a new version id serving, and a green smoke check on the live site — both now automatic on merge.
- ⛔ A green deploy alone is not acceptance. That mistake is what this card's own history is made of.
- State plainly what was verified before merge and what could only be verified after.
Re-check
# what is serving, and the size of the last accepted upload
gh workflow run rollback-docs.yml # blank version_id = list only, changes nothing
gh run list --workflow=ci.yml --branch=main --limit=5
# the multiplier, on the current tree
git show origin/main:apps/docs/source.config.ts
Related: #262 (nothing measures the bundle — at 89.3% even the working fix had ~5.3 MiB of headroom) · #265 (rendering unverifiable pre-merge) · #266 (human gate, declined — detection replaced prevention) · #267 (rollback tooling) · #269 / PR #270 (the verification layer) · #272 (the beacon this card silences) · PR #263 (reverted) · PR #268 (the revert).
Current state
The site is up and serving Worker version
69c79ee3-…(2026-08-25). It is stale: everything merged since then is onmainand not published.Deploys are rejected.
deploy-docs.ymlbuilds a Worker over Cloudflare's 64 MiB uncompressed limit; the upload is refused at version creation withcode: 10027. A rejected upload creates no version, so the good version keeps serving. As of #269 that failure is no longer silent — it files and updates #272.The defect
fumadocs-mdximports every page eagerly, so all seven locales' compiled corpus is inlined into every server entrypoint that touchessource— the docs page,/llms.txt,/llms-full.txt,/llms.mdx/*,/og/*,/api/search,/sitemap.xml— and the bundler then inlined that set five times over.The content is not the weight. All 397
.mdxfiles total 2.50 MiB;handler.mjsmeasured ~110 MiB. A probe sentence occurring once in one English page appeared 15 times in the bundle. A 40x bundling multiplier is the weight. ⛔ A fix that deletes documentation to fit is the wrong fix.The margin was never healthy. Run #105, the last good deploy, logged
Total Upload: 62747.87 KiB— 95.7% of the limit. The commit that crossed it (c243ad79) was 15 lines and made its own output smaller. Anything landing that week would have done it.⛔ What the previous attempt got right, and the one thing nobody knows
PR #263 set
async: trueon the docs collection:handler.mjs100.93 → 48.47 MiB locally, 58541 KiB (89.3%) measured in CI. It was ablation-verified under real workerd — breaking a lazy thunk took/api/searchfrom 200/22890 B to 500/0 B and a byte-identical restore brought it back.It was merged, the upload was accepted, and the site broke. Rolled back within ~20 minutes, then reverted (PR #268).
Nobody diagnosed why it broke rendering. That is the open question and it is the first deliverable here — not the fix. The diagnosis was right about the cause of the size; what it did to the render path was never established, only observed.
⛔ Do not re-apply PR #263's diff and hope. If
async: trueturns out to be the right shape after all, it has to arrive with an explanation of why it broke rendering last time and what makes it safe now.Verification, and what changed since the last attempt
Since #269 / PR #270 landed, every deploy is followed by a smoke check of the live site (4 pages, 12 structural rules, a negative control every run proving it can fail), a bad deploy auto-dispatches a rollback, and any failure files a card.
#265's investigation is in scope here if you need it. Docs page routes 404 under local
wrangler dev/opennextjs-cloudflare preview— onmaintoo, so it is pre-existing. If making that work is what it takes to see a page render before merge, do it and say so; that is a better outcome than shipping on the backstop. If it turns into a rabbit hole, stop and report rather than sinking the round into it.Acceptance
Deploy Docswith a new version id serving, and a green smoke check on the live site — both now automatic on merge.Re-check
Related: #262 (nothing measures the bundle — at 89.3% even the working fix had ~5.3 MiB of headroom) · #265 (rendering unverifiable pre-merge) · #266 (human gate, declined — detection replaced prevention) · #267 (rollback tooling) · #269 / PR #270 (the verification layer) · #272 (the beacon this card silences) · PR #263 (reverted) · PR #268 (the revert).