diff --git a/packages/ghost/ghost.mjs b/packages/ghost/ghost.mjs index 9987e61..41d8466 100644 --- a/packages/ghost/ghost.mjs +++ b/packages/ghost/ghost.mjs @@ -195,6 +195,229 @@ tick();setInterval(tick,1600);addEventListener("resize",draw); `; } +// Ghost City 3D — same layout language as the published playground (3D city in +// the center, info panel left, selected-tower panel right, turn dock bottom), +// but stream-fed from the recorder's own /session, so ANY project gets the +// full experience from `ghost watch` alone. three.js is loaded from a CDN in +// the browser (the recorder itself stays zero-dependency); if the browser is +// offline the 2D canvas city at /city2d is still served by the recorder. +function cityHtml3d() { + return ` + +Ghost City — live playground (3D) + + + +

Ghost City

connecting… + studio · session · 2D fallback +
+
+ +
+ +
+
turns
+`; +} + // ── helpers ────────────────────────────────────────────────────────────────── // Parse a unified diff into per-file churn (added+deleted lines) used as the // 3D city "height" — so towers stay a fact of the recording, never invented. @@ -319,6 +542,11 @@ async function cmdWatch() { return; } if (req.method === "GET" && req.url === "/city") { + res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" }); + res.end(cityHtml3d()); + return; + } + if (req.method === "GET" && req.url === "/city2d") { res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" }); res.end(cityHtml()); return; @@ -429,7 +657,7 @@ async function cmdWatch() { if (!session.head) console.log(` git none — file recording only (run git init to enable shadow-git checkpoints)`); console.log(` app ${appUrl}`); console.log(` studio ${eventsBase} ← detail: turns, checkpoints, samples`); - console.log(` city ${eventsBase}/city ← playground kota live (tanpa npm run dev)`); + console.log(` city ${eventsBase}/city ← playground kota 3D live (tanpa npm run dev)`); console.log(` replay full 3D dashboard: repo → npm run dev → /playground?live=1`); console.log(` adapter ${eventsBase}/events (OpenCode plugin target)`); console.log(` sync ${sync}${sync === "off" ? " (local-only) — run: ghost setup to enable" : ""}`);