← BACK TO SITE MONOLITH STUDIO / BUILD GUIDE
Documentation

How This Site
Was Built.

A working record of the concept, the art direction behind the imagery, the build techniques, and the deployment path behind the Monolith Studio showcase — written so the decisions can be reproduced or adapted.

01 — Concept

Monolith Studio is a fictional brutalist architecture practice. The brief was to push swiss/international-typographic grid discipline to a brutalist extreme: oversized grotesque type, hard edges, a raw monochrome palette, exactly one bold accent color, and a visible structural grid — the layout itself reads like a working drawing, not a decorated page.

The core visual conceit is that the page behaves like the buildings it's describing: elements are gridded, load-bearing, and unornamented. The only "decoration" allowed is the accent color, used the way a site foreman uses hazard paint — sparingly, to mark the one thing that matters.

02 — Palette & Type

Black #0a0a0a
White #f2f1ec
Concrete #a9a49b
Concrete Dk #57544d
Accent #ff3300

Type is a single grotesque family, Archivo (Google Fonts, weights 100–900), used at extreme contrast — a ~10–13vw display weight for headlines against 11px mono labels for metadata. The mono counterpart is Space Mono, used exclusively for coordinates, index numbers, captions and the roster — anything that reads as "annotation" rather than "statement."

Both are loaded as standard <link> tags from Google Fonts — no build step, no self-hosting, matching the plain HTML/CSS/JS constraint for this build.

03 — Imagery: art direction

All eight photographs were generated with Higgsfield's Nano Banana Pro model at 2K resolution, then converted to compressed JPEG at 1920px max width with macOS sips to keep the folder lightweight (~7.5 MB total across 8 images). Each image — the hero mass shot, the six project photographs, and the board-formed concrete detail — was generated from a carefully art-directed brief specifying the lens, light direction, grain, composition, and mood, biased toward genuine architectural photography conventions rather than a generic "brutalist building" description, which tends to produce illustration-like results. Each was iterated until it held the monochrome print quality of the set. The full prompt library is proprietary and available to clients on request.

Why black and white at the source, not a CSS filter alone? Directing the model to monochrome directly produces correct tonal separation and grain at the source. A light grayscale(1) contrast(1.1) CSS filter is still applied on top in style.css as a safety net so any color drift between generations reads as one consistent print.

04 — The scroll-driven 3D building massing

This is the site's signature technique, in js/scene.js. It is not a looping animation — it is a deterministic function of scroll position, built on plain Three.js (r149, UMD build, no bundler) and GSAP ScrollTrigger for the scroll math.

How it works

  1. Six extruded volumes (THREE.BoxGeometry) stand in for a stepped brutalist massing: a podium, a core tower, a cantilevered block, a support fin, a podium wing, and one slim accent-colored blade — mirroring the "one bold accent, used sparingly" rule in 3D.
  2. Every volume gets a matching THREE.LineSegments built from THREE.EdgesGeometry, drawn in off-white at low opacity. This is what gives the forms their technical-drawing edge — a low-poly box alone reads as a toy; a box with crisp wireframe edges reads as a structural diagram.
  3. Each volume has four keyframe positions — MASS, VOID, CANTILEVER, ASSEMBLY — hand-placed to tell a specific structural story: everything starts collapsed into one undivided block, then separates to open gaps ("void"), then the cantilevered block is pushed dramatically outward past its support, then the whole composition locks into its final stepped form.
  4. A single ScrollTrigger is created on the pinned #assembly section (scrub: 0.5, no markers). Its onUpdate callback receives self.progress (0→1 across the pin) every scroll tick and calls applyProgress().
  5. applyProgress() divides progress into three equal segments, applies a smoothstep ease within the active segment, and linearly interpolates each volume's position between its keyframes for that segment — this is what makes the assembly feel directly grabbed by the scrollbar rather than playing on a timer.
  6. The whole group also rotates (group.rotation.y = progress * Math.PI * 0.85) and the camera slowly dollies in (camera.position.z lerped from 13.5 → 10.6) over the same progress value, so orbit and dolly are scroll-scrubbed too, not just the assembly.
  7. The accent blade fades in via material opacity only after progress passes 0.36 — a deliberate reveal so the one accent color arrives as a payoff partway through the sequence rather than being visible from frame one.
  8. The same progress value drives the on-screen mono labels (stage number, stack list, caption heading/copy) via a small stage-index lookup — DOM and 3D read from the identical scroll number, so they can never drift out of sync.
Why pin for 340vh instead of a short 100vh hero loop? A short pin makes the sequence feel like a decorative GIF. Stretching the scroll distance to 340vh gives each of the four stages roughly a full screen-height of scroll to read, so a user scrubbing slowly actually watches the structure argue its way into place instead of blowing past it in one flick.

Hero canvas (secondary scene)

The hero background runs a second, lighter Three.js scene: the same six-volume language in an ambient exploded cluster that idles with a slow autorotation and gets a subtle additional rotation/parallax tied to hero scroll progress. It exists to make the page feel alive on load, before the user has scrolled far enough to reach the pinned assembly sequence.

Performance / mobile degrade

05 — Other techniques worth naming

Visible swiss grid as a design element

A fixed, pointer-events-disabled 12-column overlay (.grid-overlay) sits above the whole page at mix-blend-mode: difference, so the column rules stay visible against both the black hero and the white section backgrounds without needing two separate color variants. Its opacity is nudged up slightly by GSAP once the "Works" section scrolls into view, reinforcing the transition from hero to content.

Line-item project list instead of a photo bento grid

The projects section (#works) intentionally is not a conventional image grid. Each project is a single full-width typographic row (index, name, meta, arrow) — closer to a drawing schedule than a portfolio tile. Hovering a row on desktop drives a small floating image preview that follows the cursor (GSAP quickTo-style tweening on mousemove); clicking a row expands a full-bleed image panel inline via a height transition. This keeps the page's information density brutalist and text-first while still surfacing the generated photography.

Coordinate-readout cursor

On fine-pointer devices, the default cursor is replaced with a small ring that reports live X/Y pixel coordinates, styled like a drafting cursor. It's throttled to one DOM write per animation frame via requestAnimationFrame, and is skipped entirely on touch devices via a (hover: hover) and (pointer: fine) media query check in JS, so it never intercepts taps on mobile.

Marquee strip

A single CSS @keyframes marquee (transform: translateX(-50%) on a doubled span) carries the material vocabulary — STRUCTURE, MATERIAL, VOID, MASS, LIGHT, LOAD — as a horizontal band between Philosophy and Process. It's pure CSS, no JS, and duplicated content rather than JS-cloned so it works even if scripts fail to load.

06 — Responsiveness

BreakpointWhat changes
<900pxGrid overlay drops to 6 columns; top nav collapses to a MENU toggle; assembly's side stack list hides (caption block remains); all section grids reflow to a 6-column layout; hover-only preview thumbnail is disabled.
<760pxThree.js pixel ratio cap drops to 1.4 and antialiasing turns off in both scenes.
<480pxContact info columns stack to full width.

Verified at 375px and standard desktop widths — text never overflows its column, the pinned assembly section still resolves to a readable single caption block, and contrast (near-black text on off-white, off-white on near-black) stays well above WCAG AA at every size.

07 — Deployment

This is a static site with zero build step — plain HTML/CSS/JS plus CDN-hosted GSAP and Three.js and Google Fonts. Deployment is a drag-and-drop or CLI push of the monolith-studio/ folder to Netlify:

  1. Create a new Netlify site and point it at this folder (or connect the repo and set the publish directory to monolith-studio/).
  2. No build command is required — set the publish directory only; there is nothing to compile.
  3. Netlify serves index.html at the root and guide/index.html at /guide/ automatically since both are already laid out as static files with relative asset paths.
  4. Because every asset reference in the HTML/CSS is relative (e.g. assets/hero-monolith.jpg), the folder is portable to any static host without path rewrites.
We do not decorate structure. We reveal it.