feat(pages): deploy three.js demos to gh-pages/three.js/ (#649)

Adds a new GitHub Pages workflow that publishes the ADR-097 three.js
demo gallery alongside the existing observatory/, pose-fusion/,
pointcloud/, and nvsim/ deployments. Uses keep_files: true so the
other deployments are preserved.

What ships:
* `examples/three.js/index.html` — new landing page that lists all 5
  demos with screenshots, "standalone" vs "needs FBX" badges, and an
  honest note explaining the Mixamo X Bot.fbx license boundary
  (demos 04 and 05 need a local download from mixamo.com; demos
  01-03 run standalone in any modern browser).
* `.github/workflows/threejs-pages.yml` — staged copy of demos/,
  screenshots/, README.md, and the new index.html into
  `_site/three.js/`. Drops an `assets/README.txt` placeholder
  explaining the FBX-not-shipped policy. Triggered on changes to
  examples/three.js/** or the workflow itself.
* README.md — adds the live link to the existing demo row
  (`▶ three.js Demos (5)`) plus a one-line callout describing the
  gallery and the FBX caveat.

After this PR merges, the workflow runs and publishes:
  https://ruvnet.github.io/RuView/three.js/
This commit is contained in:
rUv 2026-05-19 18:17:43 -04:00 committed by GitHub
parent 67fec45e61
commit d67d9872c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 242 additions and 0 deletions

70
.github/workflows/threejs-pages.yml vendored Normal file
View File

@ -0,0 +1,70 @@
name: three.js demos → GitHub Pages
# Publishes the ADR-097 three.js demos under gh-pages/three.js/.
# Uses keep_files: true so the existing observatory/, pose-fusion/,
# pointcloud/, nvsim/, and root index.html demos are preserved.
#
# Demos 04 and 05 require a Mixamo "X Bot.fbx" placed in assets/.
# That file is intentionally gitignored (license boundary), so this
# workflow does NOT ship it. Demos 01-03 work standalone; the index
# page documents the FBX requirement honestly.
on:
push:
branches: [main]
paths:
- 'examples/three.js/**'
- '.github/workflows/threejs-pages.yml'
workflow_dispatch:
permissions:
contents: write
concurrency:
group: threejs-pages
cancel-in-progress: true
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout main
uses: actions/checkout@v4
- name: Stage demos for Pages
run: |
mkdir -p _site/three.js
# Copy everything except the local Python server (CI doesn't need it)
# and any stray scratch screenshots.
cp -r examples/three.js/demos _site/three.js/demos
cp -r examples/three.js/screenshots _site/three.js/screenshots
cp examples/three.js/README.md _site/three.js/README.md
# An index.html that lists the 5 demos with the FBX caveat.
cp examples/three.js/index.html _site/three.js/index.html
# Mixamo FBX is gitignored — assets dir won't exist in CI.
# Drop an empty placeholder so the relative path 'assets/' resolves
# to a directory listing (404 on missing file) instead of an opaque
# network error. Browsers showing the 404 path makes the failure
# visible to anyone trying demos 04/05 without their own FBX.
mkdir -p _site/three.js/assets
cat > _site/three.js/assets/README.txt <<'EOF'
The Mixamo "X Bot.fbx" required by demos 04-skinned-fbx.html and
05-skinned-realtime.html is intentionally not redistributed here.
Download your own from https://mixamo.com (FBX Binary, T-Pose,
Without Skin) and place it here as "X Bot.fbx" if you want to
run those demos locally. See examples/three.js/README.md in the
repo for context.
EOF
echo "Staged contents:"
ls -R _site/three.js/ | head -30
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: _site
# Critical: preserve observatory/, pose-fusion/, pointcloud/, nvsim/
# and the root index.html already on gh-pages.
keep_files: true
commit_message: 'three.js demos: ${{ github.event.head_commit.message }}'

View File

@ -117,10 +117,14 @@ node scripts/mincut-person-counter.js --port 5006 # Correct person counting
<a href="https://ruvnet.github.io/RuView/pose-fusion.html"><strong>▶ Dual-Modal Pose Fusion Demo</strong></a>
&nbsp;|&nbsp;
<a href="https://ruvnet.github.io/RuView/pointcloud/"><strong>▶ Live 3D Point Cloud</strong></a>
&nbsp;|&nbsp;
<a href="https://ruvnet.github.io/RuView/three.js/"><strong>▶ three.js Demos (5)</strong></a>
> The [server](#-quick-start) is optional for visualization and aggregation — the ESP32 [runs independently](#esp32-s3-hardware-pipeline) for presence detection, vital signs, and fall alerts.
>
> **Live ESP32 pipeline**: Connect an ESP32-S3 node → run the [sensing server](#sensing-server) → open the [pose fusion demo](https://ruvnet.github.io/RuView/pose-fusion.html) for real-time dual-modal pose estimation (webcam + WiFi CSI). See [ADR-059](docs/adr/ADR-059-live-esp32-csi-pipeline.md).
>
> **three.js scene gallery** at [`/three.js/`](https://ruvnet.github.io/RuView/three.js/) — five progressively richer ADR-097 demos: helpers, cinematic, GLTF skinned, FBX skinned, and a live MediaPipe→Mixamo retargeting feed driven by ESP32 CSI. Demos 04 and 05 require a local Mixamo `X Bot.fbx` (license boundary — not redistributed).
## 🤗 Pretrained model on Hugging Face

View File

@ -0,0 +1,168 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex,nofollow">
<title>RuView · three.js demos · ADR-097 sensing-helpers scene</title>
<style>
:root {
--bg: #0a0e1a;
--bg2: #111627;
--card: #171d30;
--card-h: #1e2540;
--border: #252d45;
--t1: #e0e4f0;
--t2: #8890a8;
--cyan: #4ecdc4;
--green: #6bcb77;
--amber: #d4a574;
--r: 10px;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
background: var(--bg);
color: var(--t1);
line-height: 1.5;
padding: 24px 16px 64px;
}
.wrap { max-width: 980px; margin: 0 auto; }
h1 { font-size: 22px; color: #fff; }
h1 span { color: var(--cyan); }
.lede { color: var(--t2); margin: 8px 0 24px; font-size: 14px; max-width: 70ch; }
.pill {
display: inline-block;
padding: 2px 8px;
border-radius: 999px;
font-size: 11px;
margin-left: 8px;
vertical-align: middle;
border: 1px solid var(--border);
background: var(--bg2);
color: var(--t2);
}
.pill.ok { color: var(--green); border-color: #2d4a35; background: rgba(107, 203, 119, 0.08); }
.pill.warn { color: var(--amber); border-color: #4a3d2d; background: rgba(212, 165, 116, 0.08); }
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 12px;
margin-top: 16px;
}
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--r);
padding: 16px;
text-decoration: none;
color: inherit;
transition: background 0.12s, border-color 0.12s, transform 0.12s;
}
.card:hover {
background: var(--card-h);
border-color: var(--cyan);
transform: translateY(-1px);
}
.card h2 { font-size: 15px; color: #fff; margin-bottom: 6px; }
.card .sub { color: var(--t2); font-size: 13px; }
.card img {
margin-top: 10px;
width: 100%;
aspect-ratio: 16/9;
object-fit: cover;
border-radius: 6px;
border: 1px solid var(--border);
background: #000;
}
.note {
margin-top: 28px;
padding: 14px 16px;
background: rgba(212, 165, 116, 0.06);
border-left: 3px solid var(--amber);
border-radius: 6px;
font-size: 13px;
color: var(--t1);
}
.note b { color: var(--amber); }
code {
font-family: 'Cascadia Code', Consolas, monospace;
background: var(--bg2);
padding: 1px 5px;
border-radius: 3px;
color: var(--cyan);
font-size: 12px;
}
a { color: var(--cyan); }
.foot {
color: var(--t2);
font-size: 12px;
margin-top: 32px;
text-align: center;
}
.foot a { color: var(--cyan); }
</style>
</head>
<body>
<div class="wrap">
<h1>RuView · <span>three.js demos</span></h1>
<p class="lede">
Five progressively richer browser demos of the <a href="https://github.com/ruvnet/RuView/blob/main/docs/adr/ADR-097-adopt-rvcsi-as-ruview-csi-runtime.md">ADR-097</a>
sensing-helpers scene, ending with a live MediaPipe-Pose → Mixamo X Bot retargeting pipeline driven
by a real ESP32 CSI feed.
</p>
<div class="grid">
<a class="card" href="demos/01-helpers.html">
<h2>01 · Helpers <span class="pill ok">standalone</span></h2>
<div class="sub">Plain ADR-097 helpers in the point-cloud viewer. No external assets.</div>
<img src="screenshots/01-helpers.png" alt="01 screenshot">
</a>
<a class="card" href="demos/02-cinematic.html">
<h2>02 · Cinematic <span class="pill ok">standalone</span></h2>
<div class="sub">Cinematic camera + pseudo-CSI visualization on top of #01.</div>
<img src="screenshots/02-cinematic.png" alt="02 screenshot">
</a>
<a class="card" href="demos/03-skinned.html">
<h2>03 · Skinned (GLTF) <span class="pill ok">standalone</span></h2>
<div class="sub">GLTF skinned mesh + additive animation blending in the ADR-097 scene.</div>
<img src="screenshots/03-skinned.png" alt="03 screenshot">
</a>
<a class="card" href="demos/04-skinned-fbx.html">
<h2>04 · Skinned FBX <span class="pill warn">needs FBX</span></h2>
<div class="sub">Mixamo X Bot via FBXLoader. Requires a local <code>assets/X Bot.fbx</code>.</div>
<img src="screenshots/04-skinned-fbx.png" alt="04 screenshot">
</a>
<a class="card" href="demos/05-skinned-realtime.html">
<h2>05 · Realtime (Pose + CSI) <span class="pill warn">needs FBX</span></h2>
<div class="sub">Webcam → MediaPipe Pose Heavy → Mixamo IK retarget, live ESP32 CSI overlay.</div>
<img src="screenshots/05-skinned-realtime.png" alt="05 screenshot">
</a>
</div>
<div class="note">
<b>Demos 04 and 05 need a Mixamo asset.</b> The Mixamo
<code>X Bot.fbx</code> file is intentionally <em>not</em> redistributed in
this deployment — it's licensed for end-users to download from
<a href="https://mixamo.com" target="_blank" rel="noopener">mixamo.com</a> directly.
To run these locally: clone the repo, download <code>X Bot.fbx</code>
(FBX Binary, T-Pose, Without Skin) into
<code>examples/three.js/assets/</code>, then run
<code>python examples/three.js/server/serve-demo.py</code>.
</div>
<div class="foot">
Source: <a href="https://github.com/ruvnet/RuView/tree/main/examples/three.js">github.com/ruvnet/RuView/tree/main/examples/three.js</a>
&nbsp;·&nbsp; ADR-097 · three.js r128
</div>
</div>
</body>
</html>