The arcade moved to monsterrobot.games, where every game lives under
/games/<name>/. BLOBBO's build was pinned to base '/blobbo/', so at the new
mount its absolute /blobbo/assets/... requests 404'd and the module loader got
HTML (the error John hit). Fix:
- vite base -> './' (relative). One build now works at ANY mount point:
index.html + editor.html sit at the deploy root, assets resolve as
./assets/... against the (trailing-slash) page URL, and assetUrl() reads
import.meta.env.BASE_URL='./' so the manifest resolves the same way. Verified
by serving dist/ under a /games/blobbo/ subpath locally: game + editor boot,
manifest fetch resolves to /games/blobbo/assets/manifest.json.
- deploy.sh publishes to the RIGHT place for each host. monsterrobot.games's
docroot is bind-mounted READ-ONLY into forum-nginx from host
/home/humanjing/monsterrobot.games/games/blobbo, so it's rsync'd on the host
(docker cp is refused on the ro mount). partly.party's container-internal
/blobbo stays a best-effort docker-cp copy. Both overlay (keep old chunks;
prune >7d) and both are verified live (index 200 + entry chunk is JS).
Live-verified: monsterrobot.games/games/blobbo/ boots (world+blob, course
select, no console errors); partly.party/blobbo/ still boots too.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root-cause fix for "Failed to load module script: got text/html" on the live
game. Assets are content-hash-named; the deploy used to `rm -rf` the web root
before copying, so any browser/CDN holding a PREVIOUS index.html asked for
chunks that no longer existed — nginx served the HTML fallback (200 text/html)
and the module loader choked. Shipping 7 times in one session made stale-index
clients common.
- Step 3 now OVERLAYS (docker cp over the top, no rm), keeping old chunks alive
as a grace window so a cached index.html still resolves. Prunes only files
orphaned >7 days (current chunks get a fresh mtime every build) so /assets
can't grow without bound.
- Step 4 now fetches the entry chunk the LIVE index references and asserts it
comes back as application/javascript — the index-only 200 check could not
catch a broken chunk graph (a missing chunk IS a 200, as HTML). Verified it
reports "entry chunk main-*.js -> application/javascript ✓".
Note: nginx still serves index.html for any missing /assets file (masks a 404
as HTML). Fixing that (or adding Cache-Control: no-cache on index.html) touches
the SHARED forum-nginx config that serves the other partly.party games, so it's
left for a deliberate, John-signed-off change rather than done in passing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- game.ts: a forgotten Workshop swap otherwise reads as a broken game with no
way back; the pill says what is on and links to the Workshop. hasOverrides()
existed in idb.ts and nothing called it.
- deploy.sh: fail if dist/ exceeds 10MB. stage-farm-assets.sh copies 43MB of
raw GLBs into public/, vite copies public/ into dist/, and deploy rsyncs all
of dist/ — I hit exactly this while browser-testing (47MB build).
Browser-verified end to end: stock boot clean (44 scene children, blob r=0.5,
no console errors), Workshop lists all 18 slots, real .glb drop swaps the stage,
Save writes a raw ArrayBuffer manifest, the game loads it (120k-tri boot renders
in-game), pill appears, Clear restores the stock scene exactly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>