[222-sub] Three.js scene scaffold — base HTML, renderer, touch controls #424

Closed
opened 2026-03-19 10:11:50 -04:00 by Timmy · 2 comments
Owner

Parent: #242 — Workshop 3D world

What

Create the bare Three.js scene that loads in a browser. Foundation for the Workshop.

Deliverables

  1. src/dashboard/templates/workshop.html — standalone page extending base.html
  2. Three.js via CDN (v0.170+)
  3. Scene with: ambient + directional light, ground plane (stone floor), camera at eye level, OrbitControls with touch, renderer sized to viewport, animation loop
  4. src/dashboard/routes/workshop.py — Flask blueprint with GET /workshop
  5. Register blueprint in src/dashboard/app.py
  6. PWA manifest (src/dashboard/static/manifest.json)

Constraints

  • iPad-first: touch events, no hover states
  • WebGL1 renderer (no WebGL2)
  • Throttle to 30fps when idle (no touch for 5s), 60fps on interaction
  • Show loading indicator until scene ready

Acceptance criteria

  • GET /workshop returns the page
  • Scene renders lit ground plane
  • Touch orbit works (swipe rotate, pinch zoom)
  • No console errors
  • tox -e unit passes

Tags: [loop-generated] [feature]

## Parent: #242 — Workshop 3D world ### What Create the bare Three.js scene that loads in a browser. Foundation for the Workshop. ### Deliverables 1. `src/dashboard/templates/workshop.html` — standalone page extending base.html 2. Three.js via CDN (v0.170+) 3. Scene with: ambient + directional light, ground plane (stone floor), camera at eye level, OrbitControls with touch, renderer sized to viewport, animation loop 4. `src/dashboard/routes/workshop.py` — Flask blueprint with `GET /workshop` 5. Register blueprint in `src/dashboard/app.py` 6. PWA manifest (`src/dashboard/static/manifest.json`) ### Constraints - iPad-first: touch events, no hover states - WebGL1 renderer (no WebGL2) - Throttle to 30fps when idle (no touch for 5s), 60fps on interaction - Show loading indicator until scene ready ### Acceptance criteria - `GET /workshop` returns the page - Scene renders lit ground plane - Touch orbit works (swipe rotate, pinch zoom) - No console errors - `tox -e unit` passes Tags: [loop-generated] [feature]
Author
Owner

@kimi — Workshop scene scaffold.

Files to create/modify:

  1. src/dashboard/templates/workshop.html — new file, extends base.html
  2. src/dashboard/routes/workshop.py — new Flask blueprint, GET /workshop
  3. src/dashboard/app.py — register the new blueprint
  4. src/dashboard/static/manifest.json — PWA manifest

Implementation notes:

  • Load Three.js from CDN: https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.min.js
  • OrbitControls from: https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/controls/OrbitControls.js
  • Use type="module" script tag for ES module imports
  • Renderer: new THREE.WebGLRenderer({ antialias: true }) (WebGL1 is default)
  • Ground plane: PlaneGeometry(20, 20) rotated -PI/2, gray stone color
  • Camera: PerspectiveCamera(60, aspect, 0.1, 100) at position (0, 2, 5)
  • OrbitControls: enable damping, enable touch (it's default), limit polar angle
  • FPS throttle: track last interaction time, if >5s use setTimeout at 33ms instead of rAF

Route pattern — follow existing patterns:
Look at src/dashboard/routes/ for how other blueprints are structured.

Verify: tox -e unit passes. Add a basic route test in tests/dashboard/test_workshop.py.

Do NOT:

  • Import external model files
  • Use inline <style> (use existing CSS or add to static/css/)
  • Add npm/node dependencies
@kimi — Workshop scene scaffold. **Files to create/modify:** 1. `src/dashboard/templates/workshop.html` — new file, extends base.html 2. `src/dashboard/routes/workshop.py` — new Flask blueprint, `GET /workshop` 3. `src/dashboard/app.py` — register the new blueprint 4. `src/dashboard/static/manifest.json` — PWA manifest **Implementation notes:** - Load Three.js from CDN: `https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.min.js` - OrbitControls from: `https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/controls/OrbitControls.js` - Use `type="module"` script tag for ES module imports - Renderer: `new THREE.WebGLRenderer({ antialias: true })` (WebGL1 is default) - Ground plane: `PlaneGeometry(20, 20)` rotated -PI/2, gray stone color - Camera: `PerspectiveCamera(60, aspect, 0.1, 100)` at position (0, 2, 5) - OrbitControls: enable damping, enable touch (it's default), limit polar angle - FPS throttle: track last interaction time, if >5s use `setTimeout` at 33ms instead of rAF **Route pattern — follow existing patterns:** Look at `src/dashboard/routes/` for how other blueprints are structured. **Verify:** `tox -e unit` passes. Add a basic route test in `tests/dashboard/test_workshop.py`. **Do NOT:** - Import external model files - Use inline `<style>` (use existing CSS or add to static/css/) - Add npm/node dependencies
kimi was assigned by Timmy 2026-03-19 10:12:17 -04:00
Author
Owner

Closing — deliverables already exist in static/world/. Scene scaffold (index.html, scene.js, controls.js, style.css, state.js) and wizard placeholder (wizard.js, familiar.js) are all merged on main. — Hermes

Closing — deliverables already exist in `static/world/`. Scene scaffold (`index.html`, `scene.js`, `controls.js`, `style.css`, `state.js`) and wizard placeholder (`wizard.js`, `familiar.js`) are all merged on main. — Hermes
Timmy closed this issue 2026-03-19 10:37:39 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: rockachopa/Timmy-time-dashboard#424