One crystal. Four phases. A portfolio that transforms as you scroll.
A customizable Three.js journey through crystal, particles, portals, and liquid metal.
One persistent canvas, crawlable content, adaptive performance, and a reduced-motion fallback.
Website · The journey · Customization · Architecture
bun install
bun devOpen localhost:3000, then scroll through the four acts. Move the pointer through the particle field and liquid surface, and hover over a project portal to enlarge it; clicking follows its configured link.
| Act | Rendering | Experience |
|---|---|---|
| Crystal | Refractive icosahedron in a procedural environment | Establishes the resting state and hero |
| Particles | GPU-driven point field with shader-based motion | The pointer repels and disturbs the field |
| Portals | Framed React Three Fiber mini-scenes | Hover enlarges each portal; click follows its configured link |
| Liquid | Full-screen raymarched chrome metaballs | The pointer pushes and reshapes the surface |
components/canvas/FacetRuntime.tsxturns scroll, pointer, and motion preferences into shared state.lib/phase.tsmaps normalized page progress to each act's local progress and cross-fade weight.components/canvas/Scene.tsxowns one persistent React Three Fiber canvas; most act-level animation idles when its scene is not visible.- The DOM overlay remains server-rendered and crawlable while the WebGL scene mounts client-side.
- Adaptive DPR scales pixel ratio, the performance monitor adjusts liquid
raymarch steps, and the initial device tier sets particle count;
prefers-reduced-motionreplaces the canvas with a static poster.
See DESIGN.md for the rendering model and extension seams.
| Change | Source |
|---|---|
| Headings, copy, phase names, and accent colors | lib/acts.ts |
| Project names, blurbs, links, colors, and portal shapes | lib/projects.ts |
| Contact link and page composition | app/page.tsx |
| Individual shaders and scenes | components/acts |
| Canonical metadata URL | NEXT_PUBLIC_SITE_URL |
The starter ships with placeholder projects and contact details; replace them before publishing a portfolio.
| Command | Purpose |
|---|---|
bun dev |
Start the Next.js development server |
bun run build |
Create a production build |
bun start |
Serve the production build |
bun run typecheck |
Run TypeScript without emitting files |
bun run lint |
Check the project with Biome |
bun run format |
Format the project with Biome |
bun test |
Run the phase-math unit tests |
Local and preview environments stay public. Production always reads the fleet gate configuration—even when the gate is unlocked—and requires:
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY |
Browser-side Clerk provider |
CLERK_SECRET_KEY |
Server-side Clerk access |
GATES_ORG_ID |
Organization that stores the fleet gate flags |
GATES_APP_ID=facet |
This deployment's gate key |