The browser engine is a port of the Python one and CI proves it: all 21.2M (guess, answer) pairs hashed on both sides to the same SHA-256. Six TS tests, including the duplicate-letter table and the twelve pinned seed vectors that keep ?seed= permalinks pointing at the same word the recording used. Word lists are split by how they are used. answers.json is inlined because the board needs it before first paint to turn a seed into a word, and a fetch there means a visibly empty board on a cold cache. guesses.json is fetched, because it is three times larger and only needed the first time somebody presses Enter; until it lands, validation falls back to the answer list, which accepts strictly fewer words. The failure mode is 'your real word was briefly rejected', not 'a non-word was accepted' — the right way round. The solver runs in a worker constructed from a same-origin module URL, never Vite's ?worker&inline: that yields a blob:, and production CSP has no worker-src, so it falls back to default-src 'self' and the worker is blocked with no console error. It would fail in production only. deploy.sh smoke-tests the real public hostname from the deploying machine and fails on a body under 1 kB, because the bind bug's signature is a valid certificate over an empty 200 and a local --resolve check passes anyway. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019mt6sHQHEnEYrJZvoMCJSB
1.6 KiB
Deploying
Static build, rsynced to cloud-2, served by Caddy.
pnpm build && bash deploy/deploy.sh
The pieces
| Host | cloud-2, ubuntu@100.92.185.76 (tailnet only) |
| Root | /var/www/demo.primeintellectgrowth.com |
| Snapshots | …-rollbacks/, last 10, hard-linked |
| DNS | OCI zone primeintellectgrowth.com → 170.9.14.61, explicit A record, no wildcard |
| Caddy | a block appended to /etc/caddy/Caddyfile |
The trap that costs an afternoon
bind 10.0.0.2 is mandatory in the Caddy block, and its absence is silent.
Without it Caddy builds a second server on *:443 that has never heard of this
hostname. Public traffic — which NATs to 10.0.0.2 — falls through to an empty
200 behind a perfectly valid certificate. Worse, a
curl --resolve demo.primeintellectgrowth.com:443:127.0.0.1 from cloud-2 itself
still passes.
deploy.sh therefore smoke-tests the real public hostname from the deploying
machine and fails on a response under 1 kB.
Do not use PIG's deploy/Caddyfile.example as a template — it omits the bind.
Rolling back
ssh ubuntu@100.92.185.76
ls -1dt /var/www/demo.primeintellectgrowth.com-rollbacks/*/
sudo rsync -a --delete <that-dir>/ /var/www/demo.primeintellectgrowth.com/
No Caddy reload needed; the root path does not change.
Editing the live Caddyfile
Scope the edit to this site's block. Several sites on cloud-2 carry
byte-identical header strings, so a naive global replace hits two of them. Slice
between demo.primeintellectgrowth.com { and the next hostname, and assert the
match is unique inside that slice.