dist/index.html was a polyglot — `#!/bin/sh`, a `<<\EOF` heredoc swallowing the whole document, the installer after the closing EOF. Both halves ran. The browser half was never honest, and could not be made honest. Anything before <!DOCTYPE html> that is not whitespace or a comment puts the document in quirks mode. Chromium, at 390 and 1280: compatMode BackCompat; document.head.children.length === 1, with all fifteen head elements — title, icons, viewport, description, every og: and twitter: tag — parsed into <body> where they do nothing; and "#!/bin/sh <<\EOF" as the first text node of the page, first string in body.innerText, pushing <main> down 24px. Proven by re-serving the identical live bytes with the 17-byte prefix stripped: BackCompat -> CSS1Compat, head.children 1 -> 15, at both widths. No arrangement of those bytes avoids it. Only whitespace and comments may precede a DOCTYPE; an HTML comment opens with `<!`, which a shell reads as a redirect from a file named `!--`, so a POSIX script cannot start there at all. The trick was unfixable, not unlucky. So the two resources become two files and `/` chooses between them by Accept, which is what HTTP has for this. worker.js is the whole rule: text/html gets dist/page.html, anything else — curl, wget, the /cli /mcp /dev shims that re-exec `curl -fsSL https://hanzo.sh` — gets dist/install.sh. `/` carries vary: accept and cache-control: no-store, because Cloudflare honours Vary only on Accept-Encoding and a shared cache holding one representation for the other kind of client breaks either the page or the install command. scripts/postbuild.js replaces the polyglot rewrite: it moves the document off index.html (Static Assets serve an exact match BEFORE the Worker runs, so a file at that name would hand curl the HTML) and writes /install from install.sh, so the alias is one file in git instead of 12,746 duplicated bytes. wrangler.toml: routes moves ABOVE [assets]. TOML puts every key after a table header inside that table, so it was parsing as assets.routes and wrangler dropped it with a warning — the custom domain survived only because it was attached out of band. html_handling and not_found_handling are "none": exact match or the Worker, nothing silently rewritten, a mistyped path still 404s. The deploy gate now checks both representations against the live URL, plus a 200 for every path the head declares — the check that would have caught og-image.svg. Verified against the real runtime before pushing: wrangler dev --local, curl gets install.sh byte-for-byte, a browser gets page.html with <!DOCTYPE html> at byte 0, `sh -n -c "$(curl -fsSL /)"` parses under dash and bash, and /index.html /nonexistent-xyz /some/deep/path still 404. Co-authored-by: Hanzo Dev <[email protected]>
33 lines
1.4 KiB
TOML
33 lines
1.4 KiB
TOML
# hanzo.sh — a Worker over static assets (CF Pages project limit reached;
|
|
# 7stars precedent).
|
|
#
|
|
# The Worker exists for one rule: `/` is the installer to curl and the landing
|
|
# page to a browser (worker.js). Every other path is a plain asset, matched
|
|
# exactly — html_handling "none" so nothing is silently rewritten or redirected,
|
|
# not_found_handling "none" so a mistyped path 404s instead of being handed an
|
|
# installer under a name that promises something else.
|
|
#
|
|
# Deploying is .github/workflows/deploy.yml, which re-fetches hanzo.sh in both
|
|
# representations and fails unless the live bytes are the ones it just built. Do
|
|
# not publish this by hand: hand-publishing is why the site served an installer
|
|
# months older than main. `npx wrangler@3 deploy` still works locally for a
|
|
# break-glass, but then main and the live host are two different states again —
|
|
# check afterwards.
|
|
name = "hanzo-sh"
|
|
main = "worker.js"
|
|
compatibility_date = "2026-07-01"
|
|
|
|
# Above [assets], not below it: TOML puts every key after a table header inside
|
|
# that table, so this used to parse as assets.routes and wrangler dropped it
|
|
# with a warning ("Unexpected fields found in assets field"). The custom domain
|
|
# survived only because it was attached out of band.
|
|
routes = [
|
|
{ pattern = "hanzo.sh", custom_domain = true }
|
|
]
|
|
|
|
[assets]
|
|
directory = "dist"
|
|
binding = "ASSETS"
|
|
html_handling = "none"
|
|
not_found_handling = "none"
|