Skip to content

Add /fundraising/stack: gated layer tour of the stack architecture - #19

Open
hhff wants to merge 35 commits into
mainfrom
feat/fundraising-stack-exploded-view
Open

Add /fundraising/stack: gated layer tour of the stack architecture#19
hhff wants to merge 35 commits into
mainfrom
feat/fundraising-stack-exploded-view

Conversation

@hhff

@hhff hhff commented Jul 22, 2026

Copy link
Copy Markdown
Member

What

The gated /fundraising/stack page, now grown into two experiences:

Locked: an 8/4 viewer grid — blurred resting trunk behind the email gate on a sage card, "The Stack" h1 (site display treatment) beside it with the fundraising body copy (bolded runtime line, hand-drawn underline on "the Android of privately intelligent hardware").

Unlocked: a ten-beat annotated layer tour of the stack architecture (docs/architecture/2026-07-22-the-stack-v2.md). It opens on the same "The Stack" intro, then each scroll section walks one layer (LAYER 01 Application RuntimeLAYER 10 FOTA & Fleet Management, copy final): the trunk re-frames per beat, paper-thin "layer" sheets build over the Orin for the software layers, consolidate into one OS slab, dissipate for the TEE dive, and the fabric beats add line-art silhouettes, the one-way Opaque Mirror riser, and the FOTA path. Hairline callouts (green tiles, mono labels, terminal nodes) annotate each beat, projected live from 3D anchors.

How

  • Timeline: pure-math module (stackTour.ts, unit-tested) owns beat windows/copy, camera keyframes, open/close explode track, sheet/slab/callout tracks, and anchor positions. The canvas is the single source of truth for the smoothed timeline value (shared by ref with the callout layer, so scene and labels cannot desync); smoothing is framerate-independent.
  • Rendering: cel-shaded — MeshToonMaterial across all bodies (clay tones on shells, CAD colours preserved on electronics) over a stepped ramp, inverted-hull silhouette outlines on the shells, ambient/key/rim lighting.
  • Render dials: ?debug=true shows a live tuning panel — shading mode (toon/lambert/PBR), cel bands, all lights + exposure, enclosure colours, outline, sheet colours, and a ground grid — exporting the tuned look as a JSON blob (renderSettings.ts store; defaults are the shipped look).
  • Asset pipeline (from the original branch work): optimize-trunk.mjs bakes the raw Fusion export to a 2.75MB meshopt GLB with 7 canonical bodies; wrapper-pivot rig preserves decode transforms.
  • Gating: unchanged; shared unlock key with /fundraising, GLB downloads after unlock, reduced motion snaps to per-beat frames (intro included).

Spec and plan committed under docs/superpowers/; built task-by-task with per-task review and a final whole-branch review.

Testing

  • 106/106 vitest (timeline math, windows, tracks, camera continuity bound, anchor arithmetic, copy contract incl. the no-em-dash rule)
  • tsc, eslint, prettier clean; smoke-tested at 200
  • Visual verification via headless-Chrome CDP rig at every beat centre, 1440 and 900 wide, plus live (non-snapped) alignment checks

🤖 Generated with Claude Code

hhff and others added 30 commits July 21, 2026 17:16
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on, fallback scope

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Dispose original Fusion meshes and intermediate baked clones so only
  the 7 joined body meshes ship in the GLB (was 838 meshes, ~106k
  orphan triangles)
- Verify against the scene graph, not the document mesh list; assert
  output document has exactly 7 meshes
- Restore brief-default quantization (14/10/12); simplify at
  ratio 0.18 / error 0.0018 (least aggressive that fits budgets)
- Fail fast on multiple scene roots; drop unused Node import

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… transforms

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…build)

Change AnimatedElementProps.as from 'keyof JSX.IntrinsicElements' to
'ElementType<{...}>' to properly constrain component prop inference.
Resolves TS2745 error where dynamic component JSX was collapsing props
to 'never' type.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
StrictMode double-invokes useMemo against useGLTF's cached singleton
scene, which nested a second pivot around each body and leaked a fresh
set of clay materials per invocation. Reuse an existing pivot when the
body is already wrapped, track the clay materials, and dispose them in
an effect cleanup on unmount.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Wrap mount effect localStorage read in try/catch for private browsing
- Conditional setUnlocked(true) instead of unconditional state set
- Guard unlock() write with try/catch, keep setUnlocked outside for storage-blocked contexts
- Maintains eslint-disable comment per precedent in sibling fundraising/page.tsx

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…k page

Prettier formatting for all 11 branch-touched files (repo had no prior format
pass). Fix misplaced eslint-disable-next-line in app/fundraising/stack/page.tsx:
disable was on the conditional line, not the setState call line, leaving the
set-state-in-effect error live. Repositioned to suppress only the intentional
synchronous localStorage read on mount.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… copy; add v2 architecture doc

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hairline callouts)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ions

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… art

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… FOTA label dedupe)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…verlay, setVisible note)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The unlocked story now begins with the same h1 + copy the locked frame
shows, camera resting on the locked card's hero pose, and scrolls into
Layer 01. Eleven scroll sections; beat i centres at (i+1)/10, track
constants remapped, and reduced motion gains an intro snap point.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The canvas now publishes its smoothed t through a shared ref that the
callout layer consumes directly, instead of each independently smoothing
scroll progress from separately-bundled modules (a stale HMR chunk could
leave them on different beat mappings, showing the wrong label for a
beat). Smoothing is also framerate independent now, so slow devices do
not trail further behind the scroll than fast ones.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ng, green linework, terminal nodes

Letter spacing drops from 0.12em to the site's ~0.03em mono convention;
labels sit on fi-green-600 tiles with fi-green-100 text; all hairlines
and static art share the same green ink; each callout line carries a
small circular node on its anchor tail and at the label junction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
hhff and others added 5 commits July 22, 2026 08:49
…500)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cel ramp

Clay shells and CAD electronics all swap to MeshToonMaterial (colours
preserved on the electronics) over a shared four-step gradient ramp.
Toon materials ignore the environment map, so both canvases gain
ambient + key + rim lights; the environment still lights the frosted
sheets. Low-poly faceting now reads as flat cel bands instead of
blocky PBR shading.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…unchier bands

Three-step ramp (harder bands keep each face of the wedge distinct),
key-weighted lighting with raised exposure for brightness, and
inverted-hull outline meshes on the four shell bodies: a BackSide copy
of each shell pushed out along its normals in the mesh's quantised
local space (per-body thickness compensates each node's scale). The
fi-green-600 outline ties the device to the callout linework.
Electronics stay outline-free.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A module-level render-settings store (defaults = the shipped look) feeds
the r3f scene and a trunk material registry that rebuilds materials live:
shading mode (toon/lambert/standard PBR), cel band count and values,
roughness/metalness, exposure, ambient/key/rim intensities and positions,
per-shell enclosure colours, sheet face/edge colours, outline
enable/colour/thickness, and a ground grid (fi-green-200 default) with
colour/opacity/size/divisions/height. Copy JSON exports the tuned blob;
Reset returns to defaults. Panel renders only with ?debug=true.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hhff hhff changed the title Add /fundraising/stack: scroll-driven exploded view of the family trunk Add /fundraising/stack: gated layer tour of the stack architecture Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant