# BeaglePlay interactive website

[index.html](index.html) is a real 3D browser viewer using the same geometry and
source connectivity as the native demo. [recording.html](recording.html) offers a two-minute beginner feature tour with
on-screen explanations, English captions, chapters and a transcript. The earlier
Ethernet/HDMI recording remains linked from that page.

## Run locally

From the repository root:

```sh
python3 -m http.server 8767 --bind 127.0.0.1
```

Open **http://127.0.0.1:8767/demos/**. Keep the terminal running while you use it.
Use HTTP rather than double-clicking the HTML file: browsers restrict module
and model loading from local file URLs. Modern Chrome, Edge, Firefox or Safari
with WebGL2 and DecompressionStream are required. Enable browser hardware
acceleration; the header reports the renderer actually used by the browser.
The browser chooses the GPU. On this Linux host the MX150 was verified with:

```sh
__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia google-chrome http://127.0.0.1:8767/demos/
```

If Chrome is already running on another GPU, open a separate browser instance
with a separate `--user-data-dir` to apply the environment to its new GPU process.
The viewer downloads approximately 40 MB of CAD, photographic and electrical
assets on first load. No Rust, Skia, Vulkan SDK, Python CAD library, npm install
or application server is needed by visitors. All runtime dependencies are local.

## Explore the model

- Left drag orbits; right drag pans. Wheel or + / − zooms deeply. Reset / R
  restores the initial view. Touch drag orbits; two fingers pan/pinch.
- **Front / Back** (F / B) show each side. **Assembly / PCB / Layers** change
  the model view. Assembly has individual enclosure checkboxes (keys 1–5).
- Hover a visible component to read its reference, type, BOM description,
  manufacturer, part number and footprint in the sidebar. Picking uses real
  triangles, with board and enclosure occlusion.
- Click a component to lock its copper connections. The selection survives
  camera, view and visibility changes. Click the model again or **Clear copper
  selection** / Escape to clear. Dragging does not change the selection.
- Large selections show **Processing connections…** and a progress bar. You can
  still move the model, change views or select another component. **Cancel
  selection**, **Clear copper selection**, Escape or another model click cancels
  unfinished copper work; canceled results cannot reappear later.
- Quick buttons focus **U6 Ethernet transceiver**, **U7 HDMI transmitter**,
  **J24 Ethernet jack** and **J4 HDMI connector**. Search any reference, part
  number, description or category and choose it from the component selector.
  These controls also support keyboard-only component inspection.
- **TP1–TP30** are selectable test pads. Hover or click the copper pad, or search
  a TP reference and select it from the dropdown. Its card shows the exact net,
  front/rear side, pad dimensions and XY position from the front lower-left board
  corner. **TP8 is on the rear**, on GBE_CLKO; TP17 is USER_BTN and TP3 is MCU_RESETZ.
  **Test points** (Y) independently hides/shows the pads. A selected TP traces its
  direct electrical net and keeps the usual click-to-clear behavior.
- **JTAG-AM62 (J19)** and **JTAG-CC1352P (J11)** have individually selectable
  pads. Search `J19.2` or `J11.2`, or hover/click the pad, to inspect its pin and
  trace only that pin's net. **JTAG pads** (J) independently switches their
  visibility. J11 pins 7 and 9 have no net assigned in the BRD; no connection
  is invented for them. Header mounting/alignment holes remain open and are
  not selectable electrical pads.
- In photo mode, TP/JTAG targets follow measured gold-pad centroids in the
  supplied photographs. The photo supplies their appearance, avoiding shifted
  gold overlays. CAD and transparent views use the exact BRD positions;
  electrical routes and the card's XY coordinates always retain BRD coordinates.
  These visibility controls hide picking/highlight targets; pads printed into
  the original photograph remain part of the photograph.
- Each selected net has one color shared by routes, pads/vias/planes and
  directly connected component outlines. Multi-net component edges use several
  colors. Hover alone never highlights copper. HDMI filters split the chip and
  connector data signals into different electrical nets.
- **Hide nets with >10 linked parts** (H) starts enabled. Exactly ten neighbors
  remain visible; larger nets stay listed with their counts. Uncheck it to
  reveal supply/ground nets. Component bodies and base artwork are retained.
  The threshold counts modeled component neighbors; connected TPs/JTAG pads are listed
  separately and do not change the existing component counts. Selecting a supply
  or ground TP can therefore start with its large net hidden until H is unchecked.
- **Transparent** (V) hides the substrate while keeping opaque front/rear
  components and actual copper artwork. **Components** (C) and **Photo** (T)
  switch component visibility and registered photo/CAD appearance.
- **Pads / Vias / Planes** (P / I / O) independently switch selected-net
  highlights. Masked fills preserve source cutouts, drilled holes and Gerber
  clearances. Planes are translucent; traces are drawn on top.
- In transparent or Layers view, choose any of the eight copper layers. Left /
  right arrows step layers; A restores all. Layers displays the exploded stack;
  orbit it to see separation. The spacing is illustrative, not a measured stackup.

## Deploy to GitHub Pages

1. Upload the complete **demos/** folder, **tests/web.test.mjs**, and
   **.github/workflows/demo-pages.yml** to a GitHub repository's **main** branch.
   Extract the deployment ZIP first and preserve its directory structure.
   Include the compressed `.gz` model/data files as ordinary Git files.
2. In **Settings → Pages → Build and deployment**, choose **GitHub Actions**.
3. Run **Actions → Publish BeaglePlay demo → Run workflow**, or push a change to
   the demo on main. The workflow checks geometry and electrical rules before
   publishing only the demos folder.
4. Open the URL in the successful deployment, normally
   `https://YOUR-USERNAME.github.io/YOUR-REPOSITORY/`.

Relative asset paths support both project sites and `USERNAME.github.io` root
sites. There is no bundler/base-path setting to change. If your default branch
has another name, update `branches: [main]` in the workflow. GitHub Pages has
not been deployed from this workspace because no Git remote is configured.
The live Cloudflare Pages site is linked below.

GitHub's [custom workflow guide](https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages)
and [publishing source settings](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site)
cover the hosting settings.

## Deploy to Cloudflare Pages

The public viewer is **https://beagleplay-3d-lab.pages.dev/** and the tutorial is
**https://beagleplay-3d-lab.pages.dev/recording.html**. The project was deployed
on 2026-10-07 using Wrangler 4.148.0, with `main` as its production branch.
Cloudflare serves the already prepared `demos/` files; it does not build Rust or
convert CAD. No GitHub connection is required.

With Node.js 22+ and npm available, sign in once on a new machine:

```sh
npx --yes wrangler@4.148.0 login --device --scopes account:read user:read pages:write
```

Complete Cloudflare's device-code authorization in your browser. Then, from the
repository root, update the existing project:

```sh
npx --yes wrangler@4.148.0 pages deploy demos --project-name beagleplay-3d-lab --branch main --commit-dirty=true
```

The stable public address stays the same; Wrangler also reports a unique URL
for each deployment. If this host's mise shim reports that no Node version is
set, prefix either command with `mise exec node@22.23.2 --`.

For a new project, the current Wrangler can redirect creation to Workers in
agent sessions. To create a Pages project directly, use
`npx --yes wrangler@4.148.0 pages project create YOUR-PROJECT --production-branch main --force`.
Here `--force` selects direct Pages creation; it does not overwrite a project.
Existing Pages deployments do not need that flag.

Alternatively, use Pages **Direct Upload / Drag and drop** with the complete
folder or `target/beagleplay-cloudflare-pages.zip`. The ZIP places `index.html`
at its root. Recreate it after site changes. The verified 43 files are below
the dashboard's 1,000-file limit; the largest asset is 20.73 MiB, below the
25 MiB individual-file limit. Keep `.gz` files intact as static payloads.

The live MP4 range check returned HTTP 200 with the complete video. Playback
works, but jumping chapters can wait for downloaded data. Cloudflare documents
this behavior in [Serving Pages](https://developers.cloudflare.com/pages/configuration/serving-pages/).
See the complete reference, build and porting guide in [SPEC.md](../SPEC.md).

## Sources and regeneration

The website preserves 802 STEP component references, 1,300,149 PCB CAD triangles,
35,518 enclosure triangles, 591 named nets, 2,749 placed pins, 14,535 sampled route
segments, 3,169 pad-layer shapes, 18,240 via-layer annuli, 345 computed fills and
2,371 physical drill contours. Repeated annuli represent 2,280 physical vias
across eight layers. Gerber raster resolution is 0.05 mm.
The 30 test-point pads are derived from February BRD pins and their exact matching
pad contours, with separate source metadata; they do not add fitted STEP parts.
Twenty J19/J11 JTAG pads are exported separately, including both unassigned pins.
All physical drill contours clip the old STEP board/surface, clearing the flat
faces that otherwise filled the mounting and header holes. Source CAD geometry
and native assets remain unchanged.

`assets/manifest.json` records input hashes, triangle ownership, registration
matrices and revision limitations. The December 2022 STEP model, February 2023
fabrication/BRD data and supplied BOM are different revisions: positions and
modeled references can differ. Absent linked references are reported explicitly.
The viewer traces direct net membership rather than inferring transitive paths.

To regenerate from the existing native cached assets:

```sh
python3 scripts/prepare_debug_pads.py
target/cad-venv/bin/python scripts/export_web.py
```

To rebuild both viewers, regenerate the native TP/JTAG assets after this export
and compile the Rust executable. The
[shared rebuild flow](../README.md#rebuild-native-and-web-viewers) includes the
complete command order, source-cache regeneration, native launch and local web
preview. After exporting, reload the browser with **Ctrl+Shift+R** and publish
the complete updated `demos/` folder for GitHub Pages.

This exporter is outside the published website; visitors use already packaged
assets. It preserves triangle order while indexing vertices and packages the
existing source-assigned connectivity with drill holes. The standalone GPL BRD
converter is not linked or shipped in the MIT browser runtime. Three.js r186 is
vendored under its MIT license; see [vendor/README.md](vendor/README.md).

## Verification

```sh
node --test tests/web.test.mjs
CDP_PORT=9226 node tests/web-browser.mjs
```

The second command needs an isolated Chrome instance with remote debugging on
that port and the site served at `http://127.0.0.1:8766/demos/` (override using
`DEMO_URL`). Unit checks validate source counts, every batched triangle's owner,
unique neighbor counting, the 10/11 boundary, distinct net colors and direct
Ethernet/HDMI connectivity. Browser checks exercise actual hover and occlusion,
mouse clicks/drags, selections, feature toggles, eight layers, enclosure parts,
photo/CAD, zoom, idle rendering, front/rear TP picking, TP selection/visibility,
and layouts down to 320 px. Screenshots are saved
under the ignored `target/web-checks/` directory.

## Re-record the beginner walkthrough

The 02:00 tutorial records the actual browser viewer on the MX150, including
camera controls, photo/CAD appearance, hover/click selection, Ethernet and HDMI,
net colors, transparency, processing/cancellation, copper switches, TP/JTAG pads,
the eight layers and enclosure. Captions explain the hardware terms in plain
English. The MP4 is 1920 × 1080, 30 fps, H.264; it has no audio narration.

The storyboard is `demos/beagleplay-beginner.json`. From the repository root,
start the local HTTP server and an isolated MX150 Chrome instance:

```sh
python3 -m http.server 8767 --bind 127.0.0.1
```

In another terminal:

```sh
__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia google-chrome \
  --user-data-dir=/tmp/beagleplay-beginner-recording --remote-debugging-port=9229 \
  --no-first-run --disable-background-timer-throttling --disable-renderer-backgrounding \
  http://127.0.0.1:8767/demos/
```

Then record and encode (requires Node.js 22+, Python 3 and FFmpeg with libx264/libass):

```sh
DEMO_URL=http://127.0.0.1:8767/demos/ node scripts/record_beginner.mjs
python3 scripts/encode_beginner.py
```

The recorder captures only that browser page, uses real viewer controls, checks
selection states and confirms the MX150 renderer. Raw frames and verification
logs go to `target/beginner-recording/`; the MP4, poster and `.vtt`/`.srt` captions
go to `demos/`. The caption band is below the app, leaving the PCB and controls
visible. Close the isolated recording Chrome instance when finished.
