From 4f4b31b9148f896c2b568d070dd18404cb034163 Mon Sep 17 00:00:00 2001 From: type-two Date: Fri, 17 Jul 2026 21:55:56 +1000 Subject: [PATCH] Deploy to partly.party/sandoniette - vite.config.ts: dev base '/', build base '/sandoniette/' (subpath deploy). - Asset loads use import.meta.env.BASE_URL so paths resolve at the subpath regardless of trailing slash. vite-env.d.ts for the env types. - deploy.sh: build -> rsync dist/ -> docker cp into forum-nginx web root /usr/share/nginx/html/sandoniette (matches the partly.party games pattern). - Verified LIVE: index+JS 200, JS served as application/javascript (not the HTML-fallback failure), PNGs image/png, title screen renders in-browser. Co-Authored-By: Claude Opus 4.8 --- OPUS-BUILD-BRIEF.md | 7 +++++++ deploy.sh | 39 +++++++++++++++++++++++++++++++++++++++ src/scenes/stage.ts | 5 ++++- src/vite-env.d.ts | 1 + vite.config.ts | 7 +++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100755 deploy.sh create mode 100644 src/vite-env.d.ts create mode 100644 vite.config.ts diff --git a/OPUS-BUILD-BRIEF.md b/OPUS-BUILD-BRIEF.md index 6bfdfd2..61b5ba5 100644 --- a/OPUS-BUILD-BRIEF.md +++ b/OPUS-BUILD-BRIEF.md @@ -1,6 +1,13 @@ # サンドニエット SANDONIETTE — Build Brief 1: The Puppet, The Food, The Samurai ## STATUS (update this as you go — a cold session reads here first) +- **LIVE 🌐** https://partly.party/sandoniette/ — `bash deploy.sh` (build base + `/sandoniette/` → rsync dist/ → docker cp into `forum-nginx:/usr/share/nginx/html/sandoniette`). + Games VPS `humanjing@100.71.119.27`, Cloudflare-fronted (purge cache after big + changes). Verified live: index+JS 200, JS is application/javascript, PNGs image/png, + title renders. `vite.config.ts` bases dev at `/`, build at `/sandoniette/`; asset + loads use `import.meta.env.BASE_URL`. Local preview needs `vite preview --base=/sandoniette/`. + - **M0 ✅** vite+ts+phaser(3.90)+Matter skeleton, harness (`window.__s`), typecheck green. Box drops → settles 68 frames, rests flush on floor. - **M1 ✅** `sim/marionette.ts` — control bar + 6 strings (head, **back**, 2 hands, diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..af36a44 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# サンドニエット SANDONIETTE — deploy to partly.party/sandoniette/ +# Games VPS: humanjing@100.71.119.27 (tailscale), docker container forum-nginx, +# nginx serves /usr/share/nginx/html// at partly.party//. +# +# Usage: bash deploy.sh (builds fresh, then ships dist/) +set -euo pipefail + +VPS="humanjing@100.71.119.27" +CONTAINER="forum-nginx" +WEB_ROOT="/usr/share/nginx/html/sandoniette" +STAGING="/tmp/sandoniette_deploy" +DIR="$(cd "$(dirname "$0")" && pwd)" + +echo "[1/5] Building (base=/sandoniette/) ..." +( cd "$DIR" && npm run build >/dev/null ) +echo " ✓ dist/ ready" + +echo "[2/5] Rsync dist/ → VPS staging ..." +ssh "$VPS" "rm -rf '$STAGING' && mkdir -p '$STAGING'" +rsync -az --delete "$DIR/dist/" "$VPS:$STAGING/" +echo " ✓ synced" + +echo "[3/5] Reset container web root ..." +ssh "$VPS" "docker exec $CONTAINER sh -c 'rm -rf ${WEB_ROOT:?} && mkdir -p ${WEB_ROOT:?}'" + +echo "[4/5] Copy bundle into container ..." +ssh "$VPS" "docker cp $STAGING/. $CONTAINER:$WEB_ROOT/" +ssh "$VPS" "rm -rf '$STAGING'" +echo " ✓ live files in place" + +echo "[5/5] Verify ..." +code=$(curl -s -o /dev/null -w '%{http_code}' https://partly.party/sandoniette/ || true) +js=$(curl -s https://partly.party/sandoniette/ | grep -o '/sandoniette/assets/[^"]*\.js' | head -1) +jscode=$(curl -s -o /dev/null -w '%{http_code}' "https://partly.party$js" || true) +echo " index: $code $js: $jscode" + +echo "" +echo "✓ Live at https://partly.party/sandoniette/ (Cloudflare-fronted; purge cache after big changes)" diff --git a/src/scenes/stage.ts b/src/scenes/stage.ts index 0c98e22..9900ce5 100644 --- a/src/scenes/stage.ts +++ b/src/scenes/stage.ts @@ -51,7 +51,10 @@ export class Stage extends Phaser.Scene { } preload(): void { - const img = (k: string) => this.load.image(k, `assets/img/${k}.png`); + // BASE_URL is '/' in dev, '/sandoniette/' in the built subpath deploy — so + // asset paths resolve regardless of a trailing slash on the URL. + const base = import.meta.env.BASE_URL; + const img = (k: string) => this.load.image(k, `${base}assets/img/${k}.png`); ['bg_washi', 'title_art', ...PORTRAITS].forEach(img); } diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..022c02a --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite'; + +// Dev serves at '/', the production build is rooted at '/sandoniette/' so it can +// live at partly.party/sandoniette/. Keep in sync with the deploy web root. +export default defineConfig(({ command }) => ({ + base: command === 'build' ? '/sandoniette/' : '/', +}));