← Basalt vault

Strata

Your data, set in stone.

Fig. 1 — Strata, live capture10 s loop · recorded frame by frame on GPU

Field notes

Scroll and the camera sinks down a shaft of hexagonal basalt columns, past four chapters, to a molten core. Instanced Three.js prisms, one small lava shader, and a scroll spring: no models, no textures.

Strata is a scroll story for a product that wants its landing page to feel deep. The page scroll drives a camera down a shaft walled with stacked hexagonal basalt columns, turning half a lap on the way. Four chapters (Surface, Sediment, Basalt, Core) fade in at their depth while a gauge counts the metres, the rock warms from dusty grey to scorched red, and sparks rise from a cracked, glowing core where the final call to action waits.

The shaft is about 1,600 instanced six-sided prisms, placed and coloured by a seeded generator, so it is identical on every load. A spring on the scroll gives the descent weight, the fog and a warm point light at the bottom do the colour grading, and the core is one short noise shader. Anyone who prefers reduced motion scrolls without the spring, and the sparks and core hold still.

How it's built

  • One draw call for the whole shaft: every basalt column is an instance of a single six-sided CylinderGeometry, scaled to its own height. A seeded generator walks two rings around the shaft and stacks columns of random height down each slot, leaving a thin joint between them, and one in ten juts inward as a ledge.
  • Depth is colour, not texture: each column gets an instance colour from its depth (sediment, shale, basalt, scorched rock), and the scene fog shifts from cold blue-black to deep red as the camera descends. A warm point light at the core and a cool headlamp riding with the camera do the rest.
  • Scroll with weight: the page is a tall empty track. Framer Motion's scroll progress goes through a spring into one shared motion value, and both the WebGL camera and the DOM chapters read that value, so text and 3D can never drift apart.
  • A lava floor that loops: the core shader samples layered noise at an offset that travels once around a circle per loop, so the flow never jumps when the 10-second preview wraps. Cracks are where the noise crosses its midline, and they are drawn brighter than white so Bloom catches them.

Inside the prompt

Every file below is written out in full, so your agent creates the project exactly — no guessing, no missing pieces.

strata-descent/
├─ .gitignore
├─ index.html
├─ package.json
├─ tsconfig.json
├─ vite.config.ts
└─ src/
   ├─ App.tsx
   ├─ index.css
   ├─ main.tsx
   ├─ vite-env.d.ts
   ├─ components/
   │  ├─ Chapters.tsx
   │  └─ StrataScene.tsx
   ├─ lib/
   │  └─ loop.ts
   └─ shaders/
      └─ coreShader.ts

Recut it

  • Rewrite the four chapters, their layer names, and depthssrc/components/Chapters.tsx → CHAPTERS
  • Rename the product in the headersrc/components/Chapters.tsx → Chapters()
  • Recolour the rock from rim to coresrc/components/StrataScene.tsx → ROCK
  • Make the shaft deeper or wider, or thin out the columnssrc/components/StrataScene.tsx → buildColumns()
  • Change how much the camera turns on the way downsrc/components/StrataScene.tsx → CameraRig()
  • Give the descent more or less inertiasrc/App.tsx → useScrollDepth()
  • Recolour the lava or change how it flowssrc/shaders/coreShader.ts → fragmentShader

Also in the vault