---
id: "2115866253390975180"
source: https://x.com/CollectUI/status/2115866253390975180
author: "Collect UI (@CollectUI)"
media: "video, 1632x1080, 26.4s"
model: claude-opus-5-5
generated: 2026-10-31
---
# Studio Portfolio with Warping Project Images

## Summary
A minimal light-grey portfolio home where one project image floats in the centre and bends, curls and slices into strips as you scroll to the next project. A huge index number counts the projects in the bottom-left, while a right-hand list of project names fades the inactive ones. The contrast between rigid Swiss typography and liquid WebGL image distortion is the lesson here.

## Style
- Theme: light (soft grey canvas, black type)
- Mood: minimal, editorial, fluid, confident, quiet
- Tags: portfolio, webgl-distortion, image-warp, swiss-type, project-index, scroll-driven, vertical-wordmark
- Category: Landing page, Motion

## Palette
| Role | Hex |
|---|---|
| Canvas grey | #EDEDED |
| Card white | #FEFEFE |
| Hairline grey | #E0E0E0 |
| Ink | #242726 |
| Dusty pink image | #C8BDC0 |
| Mauve shadow | #9E858A |
| Faded text | #F0F0F0 |
| Swatch lilac | #C9B6F2 |

## Typography
- Vertical wordmark on the left edge: bold grotesk caps rotated 90 degrees counter-clockwise, about 6% of frame height, with a circled-mark glyph. A placeholder wordmark; Inter Bold or Archivo Black.
- Main nav (Work, About, Playground, Contact): stacked uppercase grotesk, medium weight, tight 1.0 leading, about 13px, led by a thin right arrow on the active item. Inter Medium.
- Index number ("01", "02"): very large light grotesk, about 22% of frame height, tight negative tracking (-0.04em), with a tiny superscript total. Inter Light or Manrope Light.
- Project titles on the right: small uppercase grotesk 11px with 0.05em tracking; description in 8px regular sentence case, centred.
- Meta labels (Team, Launch, Recognition): 7 to 8px grey sans in a two-column key-value layout.

## Layout
- 3:2 frame showing a browser-like card with 12px radius and a soft drop shadow over a blurred photo background.
- Page is a 12-column grid: wordmark column at the far left (about 4%), nav at columns 2 to 3, meta at columns 1 to 3 mid-height, image centred on columns 5 to 8, project list centred on columns 9 to 11.
- Index number sits bottom-left at about 16% from the left, its baseline 40px above the footer row.
- Footer row: tiny "Scroll" label left and a "View showcase" link with a play triangle right, 8px.
- No borders, no visible grid lines; everything hangs off generous whitespace.

## Elements
- Floating project image: about 18% of the frame width, rendered on a plane that curls, skews and tears into vertical strips (6 to 10 slices) during transitions.
- Project list: five entries stacked vertically, each a title plus a 3-line description; the active entry is full ink, neighbours fade to 15% opacity.
- Colour swatches: two 8px squares next to the active title showing the project's brand colours.
- Meta block: Team, Launch and Recognition labels with values (agency name, month and year, award list).
- Top bar: "Menu" label, a short status line in the centre and an email link top-right, all 8px.
- Custom cursor: a small 10px ring.

## Motion
- Each project change takes about 900ms: the outgoing image curls like paper and splits into strips that fly out toward a corner, while the incoming one unfurls from the opposite side with a cubic-bezier(0.7, 0, 0.2, 1) ease.
- The index number rolls vertically (old digit up and out, new digit up and in) over 600ms.
- The right-hand list scrolls one row per project with an opacity crossfade of 400ms.
- Projects advance roughly every 4.5s in the recording (01, 02, 03, 01, 06, 01), and the cycle loops back to the first.
- Idle state: the image tilts slightly toward the cursor (max 4 degrees).

## Rebuild it
1. React page in a full-height `grid grid-cols-12`; a fixed left column holds the wordmark with `[writing-mode:vertical-rl] rotate-180`.
2. Render the active image on a React Three Fiber plane with a custom shader: a `uProgress` uniform drives a page-curl bend plus `floor(uv.x * slices)` offsets for the strip tear.
3. Tie `uProgress` to scroll with Motion `useScroll` and `useTransform`, snapping per project with `animate()` (duration 0.9, ease `[0.7, 0, 0.2, 1]`).
4. Index number: a fixed-height `overflow-hidden` box with `AnimatePresence` sliding digits on `y: '100%'` to `'-100%'`.
5. Project list: map items and set `animate={{ opacity: i === active ? 1 : 0.15 }}` with a 0.4s fade.
6. Use `bg-[#EDEDED]`, `text-[#242726]`, Inter with `tracking-tight` on the numerals.

## Generation prompt
A minimal light-grey studio portfolio homepage: a vertical bold wordmark on the left edge, a stacked uppercase nav, a huge thin "01" counter in the bottom-left, and a single floating project photo in the centre that curls like paper and tears into vertical strips as it transitions to the next project (pink abstract folds, black architectural slats, brutalist concrete building), faded project list on the right, Swiss grotesk typography, smooth and fluid.
