← Return to the listings

How this site was made

Design notes for Gramercy & Vane — a fictional ultra-luxury Manhattan brokerage built as one of twenty-five sites showcasing Claude Fable 5. Everything here was hand-written: no build step, no framework, one HTML file, one stylesheet, one module.

Three listings, made inevitable

The page has a single job: make three flagship tower residences feel like the only three that matter this season. So the site is structured as an approach by air — a wireframe Manhattan you fly through, where each tower lights up in champagne gold as its listing arrives. Full-bleed photography carries the interiors; engraved spec plates carry the facts.

Night sky, glass, and gold leaf

Ink navy#060B18
Champagne gold#C9A96A
Glass blue#7FA8C9
Interior amber#E0A35E
Paper#ECE6D8

Bodoni Moda

A true high-contrast Didone with optical sizing — the typographic equivalent of a limestone lobby. Used for mastheads, building names, and prices; the italic ampersand is the brand's one flourish.

Schibsted 40.7649° N

Schibsted Grotesk — a cool, precise grotesk with tabular figures, set small and letter-spaced for coordinates, spec labels, and the bearing HUD. Data stays data; the Didone never has to do arithmetic.

The wireframe island

The skyline is a single Three.js scene on a fixed canvas behind the whole page. About 600 buildings are generated from a seeded PRNG — same city every visit — placed on an island whose width tapers like Manhattan's, with a rectangular void for Central Park and taller height ranges for Midtown and Downtown. All 12 edges of every box are pushed into one LineSegments buffer:

const islandHalfWidth = z => 26 * Math.max(0, 1 - Math.pow(Math.abs(z) / 98, 2.3));
const inPark = (x, z) => z > -52 && z < -16 && x > -9 && x < 9;
// one draw call for ~7,000 edges
fabricGeo.setAttribute('position', new THREE.Float32BufferAttribute(fabric, 3));

The camera plays a score of six keyframes — approach, three towers, the full island, dusk — anchored to the scroll positions of the page sections and eased with a quintic smoother, then glided with a lerp so the flight feels piloted rather than scrubbed. The glints are a custom point shader that twinkles on a per-point phase:

float tw = pow(max(sin(uTime * 0.9 + aPhase * 7.0), 0.0), 10.0);
gl_PointSize = (1.4 + 3.2 * tw) * (140.0 / -mv.z);

Each flagship tower is its own line segment set plus 90 amber window points. An IntersectionObserver on the interstitial sections flips a target; the render loop lerps line color from glass blue to gold and fades the windows in — the tower literally comes home as you reach its listing. With prefers-reduced-motion, the camera snaps between keyframes, the idle sway stops, and the twinkle freezes at a fixed frame.

GPT Image 2, on assignment

This site is the GPT Image 2 half of a model face-off — its four photographs were generated with OpenAI's gpt-image-2 (hero at high quality, the rest at medium), while sibling sites in the series used Nano Banana Pro. The prompts were written like an editorial photo brief, not a description: camera format, focal length, hour, and grade — "Phase One medium format, 24mm tilt-shift, level verticals, long exposure so window lights sparkle, deep navy shadows and champagne highlights." Naming the palette inside the prompt is what keeps the photography and the CSS in the same world.

Three passes

Do this yourself

  1. Give Claude a one-line brand with a point of view — "private Manhattan brokerage, twelve residences a year" beats "real estate website."
  2. Assign a palette of four named colors and a type pairing with roles: one face for names and prices, one for data. Ban the defaults you always get.
  3. Ask for one signature element and make everything else serve it — here, a scroll-piloted wireframe city. One bold thing, disciplined surroundings.
  4. Have image prompts written like a photographer's call sheet: format, lens, hour, film grade, and your palette's exact adjectives.
  5. Demand real copy — building names, carrying costs, coordinates. Specifics are what make a fiction feel inevitable.
  6. Screenshot at desktop and 390 px, and make Claude critique the images it took before touching code again.
  7. Run three named passes: correctness, elevation, taste. In the last one, remove something.
  8. Check the unglamorous ends: keyboard focus, reduced motion, zero console errors. Luxury is mostly the absence of faults.