PRISM·COLLECTIVE — BUILD GUIDE ← Back to site
Build Notes

How this site
was built

A walkthrough of the concept, the art direction behind every image, the shader technique behind the animated background, the animation system, and how the finished static site would ship.

01 Concept

PRISM Collective is a fictional underground-but-polished electronic music label and festival collective. The brief was neon, glitch, and chromatic-aberration energy — the opposite pace of a slow luxury reveal site. Every decision was made to feel fast and snappy: short easing curves, quick reveals, an infinite marquee, a live "waveform" pulse — nothing lingers.

The reference points were Boiler Room's raw documentary energy and a label's Bandcamp/Resident Advisor presence: bold typographic hierarchy, real event listings, a releases grid, and a booking contact — a site a real label could actually ship.

Palette

#07070A — base #0D0D12 — panel #F3F1F5 — ink #FF2BD6 — magenta #14F1FF — cyan #C9FF1F — acid #7C4DFF — violet (shader only)

Magenta, cyan and acid green are used deliberately clashing rather than harmonized — no gradient blending between them in UI elements, only in the background noise field. Acid green is reserved for state/status signals (eyebrows, "few left" tags, the live-feed dot) so it always reads as "live data," not decoration.

Type pairing

RoleFontWhy
Display / headlinesUnbounded (700–900)Geometric, blocky, slightly technical letterforms with real weight contrast — reads as a rave flyer typeface without being a novelty font.
Body / labels / nav / dataJetBrains MonoA coding monospace doubles as a "systems / signal" voice — event dates, catalog numbers and nav labels read like a tracklist or a terminal.

02 Generated imagery

Eight images were generated with Higgsfield (nano_banana_pro, 2K) and converted to WebP (cwebp -q 78 -m 6) to keep the whole asset folder under 3MB — the raw PNGs came back at roughly 8–10MB each. Every prompt explicitly excludes text/logos so nothing fights the real typeset UI, and each one leans on the brand's three clashing neon accents plus visible film grain and chromatic aberration so the photography and the CSS/shader treatment feel like one material.

Each image — the prism hero texture, the warehouse crowd, the three roster portraits, the glitch texture, the festival stage, and the shattered-glass about texture — was generated from a carefully art-directed brief specifying the lighting setup, framing, palette, texture treatment, and mood, then iterated until it sat inside the brand. Direction notes worth keeping: the hero literalizes the brand mark (a prism splitting light into the three accent colors) and doubles as a release cover in the Sound grid; the three roster portraits were each directed under a different lighting setup so the grid doesn't repeat a look, and three source photos become six roster cards via a CSS hue-rotate() duotone pass; and the about texture literalizes "broken color" from the tagline. The full prompt library is proprietary and available to clients on request.

03 The animated background — the required non-generic technique

The brief called for a WebGL or canvas shader background as the site's signature technique. This site uses a raw WebGL fragment shader (no Three.js, no shader libraries) painted onto a single full-screen triangle pair — the smallest possible WebGL setup: one vertex shader that just passes through clip-space coordinates, and one fragment shader doing all the work.

How the noise field works

The fragment shader is a hand-written domain-warped fractal Brownian motion (fBm) field — the same family of technique used for procedural cloud/plasma shaders. The chain is:

  1. Value noise from a hashed 2D lattice (hash() → noise()), smoothed with a Hermite curve.
  2. fBm layers five octaves of that noise at increasing frequency / decreasing amplitude for organic, cloud-like detail (fbm()).
  3. Domain warping — the coordinates fed into one fbm() call are themselves offset by the output of two other fbm() calls (q and r in the code). This is what turns flat noise into the folded, marbled, "liquid" look instead of generic Perlin static.
  4. The final scalar field is mapped through three mix() steps into the magenta / cyan / acid palette, then dimmed with a vignette and a soft per-pixel scanline + grain pass.
vec2 q = vec2(fbm(p + t), fbm(p - t*1.3));
vec2 r = vec2(fbm(p + 1.4*q + vec2(1.7,9.2) + t*0.9),
              fbm(p + 1.4*q + vec2(8.3,2.8) - t*0.7));
float f = fbm(p + 2.2*r);

A uMouse uniform nudges the warp offset slightly toward the cursor for a subtle parallax without ever breaking the ambient loop. Time drives everything ( uTime), so the field never repeats in an obviously loop-able way over a normal viewing session.

Performance: pixel ratio is capped (1.25 on mobile, 1.75 on desktop), the canvas pauses its draw loop entirely on visibilitychange, and the shader itself is five octaves of 2D noise — cheap enough to run smoothly on integrated GPUs. A flat radial-gradient fallback covers browsers with no WebGL context.
Contrast fix (iteration pass): a fixed .scrim layer (a soft dark gradient, heavier at the very top/bottom for the nav and footer) sits between the canvas and the grain overlay. The raw noise field occasionally swings bright enough to wash out body text; the scrim guarantees a contrast floor everywhere without dulling the shader's color in the areas that matter most.

04 Animation system

GSAP 3 + ScrollTrigger (CDN) drive every motion moment. In line with the "fast, not cinematic" brief, most tweens sit at 0.4–0.7s with power3/power4.out easing rather than the slow multi-second reveals a luxury site would use.

05 Responsive approach

Two breakpoints (900px, 640px) rework grids from 3→2→1 columns and swap the inline nav for a full-screen link takeover below 640px. Two real bugs surfaced and were fixed during the responsive pass:

06 Deployment

The whole project is static — no build step, no framework, no environment variables. To ship it:

  1. Drag the prism-collective/ folder into Netlify Drop (or connect the repo and set the publish directory to this folder) — index.html is picked up automatically as the site root.
  2. No build command is required; guide/index.html and assets/* are served as-is.
  3. Point a custom domain at the Netlify site and Netlify handles TLS automatically.

Because every asset is already a relative path and every third-party dependency (Google Fonts, GSAP) loads from a CDN with no API keys, there is nothing else to configure.