IrisBackgroundsAurum Trail
Aurum Trail
A single fan of gold light trails rising from the bottom edge and bending right into a bright crest, each core rimmed with a thin violet chromatic fringe.
Aurum Trail
Built to one specific long-exposure reference photo: unlike `ignis`'s two-sided sweep into a centred flare, this is one fan of strands, mostly straight along the bottom, that bends as a single group toward a crest sitting up and to the right — the read is closer to a road curving away than a starburst. Colour stays almost entirely gold, near-white at each strand's core, with two strands turned magenta for variety; the fringe is the more particular detail — a thin violet-blue line riding just outside every gold core, the way a bright highlight disperses through a real lens rather than staying one clean colour.
No pointer interaction — the fan holds its shape regardless of the cursor, same reasoning as `gargantua` and `singularity`.
Install
No installation needed — self-contained, paste-in code.
Usage
Drop it straight into a page.
import { AurumTrailField } from "./AurumTrailField";
export default function Example() {
return (
// Fills its nearest positioned ancestor (it renders itself `absolute
// inset-0`) — give it a sized, relatively positioned box.
<div className="relative isolate h-[32rem] w-full overflow-hidden rounded-2xl">
<AurumTrailField />
</div>
);
}Component
The real source, exactly as it ships — multiple files, kept together.
"use client";
import { useEffect, useRef } from "react";
/**
* Rebuild of a long-exposure light-trail photo: a wide bundle of warm gold
* strands, spread across most of the bottom edge, in genuine perspective —
* a single `invZ` depth term (1 at the camera, ~0 at the crest) drives both
* the bundle's width and its centre line, the way `RoadField` derives its
* converging lane bundle, rather than each strand bending toward a shared
* target independently. That's what makes the strands narrow smoothly to a
* single point exactly at the crest instead of merging early and coasting
* on as a solid column. The bundle's centre itself drifts from off-centre
* at the camera to further right at the crest, which is the "bending
* right" read — a real depth cue, not a per-strand curve. A soft white-hot
* flare sits at the crest (`IgnisField`'s move), every strand rimmed with a
* thin violet/blue chromatic fringe the way a real lens disperses a bright
* highlight, plus a couple of dedicated magenta strands for variety.
*
* Deliberately NOT built on `lib/shader-surface.ts` — this owns its own GL
* context, resize handling, and animation loop rather than sharing the
* catalogue's scaffolding.
*/
const VERTEX = `
attribute vec2 a_pos;
void main() { gl_Position = vec4(a_pos, 0.0, 1.0); }
`;
const FRAGMENT = `
precision highp float;
uniform vec2 u_res;
uniform float u_time;
float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123); }
const float VP_X = 0.34; /* crest, P-space (right of centre) */
const float VP_Y = 0.76; /* crest height, uv space */
const float BASE_X = -0.12; /* bundle centre at the camera (bottom edge) */
const float FAN_W = 1.05; /* bundle half-width at the camera */
const float MIN_BW = 0.006; /* half-width floor so the bundle never collapses to zero */
void main() {
vec2 uv = gl_FragCoord.xy / u_res; // 0..1, y up
float aspect = u_res.x / u_res.y;
vec2 P = (uv - 0.5) * vec2(aspect, 1.0);
/* ground: near-black navy, gathering a soft warmth around the crest */
vec3 col = vec3(0.008, 0.011, 0.024);
vec2 vpP = vec2(VP_X, VP_Y - 0.5);
float distVP = length(P - vpP);
col += vec3(0.4, 0.18, 0.1) * exp(-distVP * distVP * 9.0) * 0.5;
/* depth: 1 at the camera (bottom edge), ~0 exactly at the crest — a real
projection, the same term RoadField derives its lane bundle from,
rather than each strand bending toward a shared x independently. */
float d = clamp(uv.y / VP_Y, 0.0, 1.0);
float invZ = pow(clamp(1.0 - d, 0.0, 1.0), 1.3);
float aboveCrest = 1.0 - smoothstep(0.9, 1.04, d);
/* the bundle's own centre line and half-width, both driven by invZ: the
width shrinks to (almost) nothing exactly at the crest, and the centre
drifts from BASE_X at the camera to VP_X at the crest — that drift,
not a per-strand curve, is the "bending right" read. */
float bundleX = mix(VP_X, BASE_X, invZ);
float bw = FAN_W * invZ + MIN_BW;
const int N = 18;
for (int i = 0; i < N; i++) {
float fi = float(i);
float t = fi / float(N - 1);
float h1 = hash(vec2(fi, 4.0));
float h2 = hash(vec2(fi, 11.0));
float h3 = hash(vec2(fi, 18.0));
/* each strand is a fixed fraction of the bundle's own half-width, so
every one of them converges on the same point together */
float lane = mix(-1.05, 0.95, t) + (h1 - 0.5) * 0.12;
float laneX = bundleX + bw * lane;
/* thickness as a fraction of the spacing BETWEEN lanes, not of the
bundle's total width — sizing it off the width instead (as a first
pass did) makes every strand overlap its neighbours into one blob
once there are more than a handful of them */
float spacing = 2.0 * bw / float(N - 1);
float thickness = mix(0.07, 0.13, h3) * spacing + 0.0006;
float dx = P.x - laneX;
float core = exp(-dx * dx / (thickness * thickness));
float glow = exp(-dx * dx / (thickness * thickness * 4.0)) * 0.22;
/* chromatic fringe: a thin violet/blue line riding just outside the
gold core, the way a bright highlight disperses through a lens —
kept tight and dim so it reads as a rim, not a colour wash */
float fringeOffset = thickness * 1.6;
float fdx = P.x - (laneX - fringeOffset);
float fringe = exp(-fdx * fdx / (thickness * thickness * 0.35)) * 0.22;
float wz = (1.0 - invZ) / max(invZ, 0.02);
float flicker = 0.85 + 0.15 * sin(wz * 0.6 - u_time * (0.4 + h2 * 0.5) + fi * 2.3);
/* the travelling light: a bright pulse riding each strand outward from
the camera toward the crest. Phased in world depth (wz), not screen
space, so it speeds up and compresses correctly as it approaches
the vanishing point instead of crawling at a constant screen-space
rate — same discipline as RoadField's dash spacing. */
float travelSpeed = mix(0.7, 1.6, h2);
float phase = fract(wz * 0.85 - u_time * travelSpeed - fi * 0.41);
float travel = smoothstep(0.0, 0.22, phase) * (1.0 - smoothstep(0.5, 0.86, phase));
vec3 gold = mix(vec3(1.0, 0.56, 0.13), vec3(1.0, 0.8, 0.4), h2);
vec3 magenta = vec3(0.86, 0.28, 0.62);
vec3 strandColor = mix(gold, magenta, step(0.96, h1));
vec3 fringeColor = vec3(0.42, 0.34, 0.92);
col += strandColor * (core + glow) * aboveCrest * flicker;
col += vec3(1.0, 0.97, 0.9) * core * aboveCrest * flicker * (1.0 - invZ) * 0.6;
col += fringeColor * fringe * aboveCrest * flicker;
col += vec3(1.0, 0.94, 0.78) * core * travel * aboveCrest * 0.9;
col += strandColor * glow * travel * aboveCrest * 0.5;
}
/* the crest flare: a soft wide bloom plus a tight hot core, independent
of the strand loop so it stays bright even where the strands
themselves have already faded into it */
float flareGlow = exp(-distVP * distVP * 22.0);
float flareCore = exp(-distVP * distVP * 160.0);
col += vec3(1.0, 0.78, 0.42) * flareGlow * 0.55;
col += vec3(1.0, 0.97, 0.9) * flareCore * 1.1;
/* vignette, darker toward the corners */
vec2 vc = uv - 0.5;
float vig = length(vc * vec2(1.0, 1.05));
col *= mix(1.0, 0.62, smoothstep(0.45, 1.1, vig));
col = max(col, 0.0);
/* dither against 8-bit banding on the dark ground */
float grain = hash(gl_FragCoord.xy + fract(u_time)) - 0.5;
col += grain * (2.5 / 255.0);
gl_FragColor = vec4(col, 1.0);
}
`;
function compile(gl: WebGLRenderingContext, type: number, src: string) {
const sh = gl.createShader(type);
if (!sh) return null;
gl.shaderSource(sh, src);
gl.compileShader(sh);
if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(sh));
gl.deleteShader(sh);
return null;
}
return sh;
}
export interface AurumTrailFieldProps {
className?: string;
}
export function AurumTrailField({ className }: AurumTrailFieldProps) {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;
/* The context is created lazily, the first time the canvas actually
comes near the viewport — not at mount. This page can carry many
canvases at once (this hero plus every card in the "similar pieces"
board below it), and a browser caps how many WebGL contexts a page
may hold open at a time (Chrome: ~16); creating one per mounted
canvas regardless of visibility means the excess is silently evicted
once that cap is hit — indistinguishable, on screen, from the
surface just being broken. */
let gl: WebGLRenderingContext | null = null;
let program: WebGLProgram | null = null;
let buffer: WebGLBuffer | null = null;
let u_res: WebGLUniformLocation | null = null;
let u_time: WebGLUniformLocation | null = null;
let started = false;
let dead = false;
const motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
let width = 0;
let height = 0;
const resize = () => {
if (!gl) return false;
const dpr = Math.min(window.devicePixelRatio || 1, 1.5);
const w = Math.max(1, Math.round(canvas.clientWidth * dpr));
const h = Math.max(1, Math.round(canvas.clientHeight * dpr));
if (w === width && h === height) return true;
width = w;
height = h;
canvas.width = w;
canvas.height = h;
gl.viewport(0, 0, w, h);
gl.uniform2f(u_res, w, h);
return true;
};
/* Idempotent: latches on the first call, so a surface that turns out
to have no usable WebGL (or loses the context race for one) doesn't
retry every time it re-enters view. */
const setup = (): boolean => {
if (started) return gl != null;
started = true;
gl = (canvas.getContext("webgl", {
alpha: false,
antialias: false,
depth: false,
stencil: false,
preserveDrawingBuffer: false,
powerPreference: "low-power",
}) || canvas.getContext("experimental-webgl")) as WebGLRenderingContext | null;
if (!gl) return false;
const vs = compile(gl, gl.VERTEX_SHADER, VERTEX);
const fs = compile(gl, gl.FRAGMENT_SHADER, FRAGMENT);
if (!vs || !fs) {
gl = null;
return false;
}
program = gl.createProgram();
if (!program) {
gl = null;
return false;
}
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(gl.getProgramInfoLog(program));
gl = null;
program = null;
return false;
}
gl.useProgram(program);
gl.deleteShader(vs);
gl.deleteShader(fs);
buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
/* one oversized triangle covers the viewport with no diagonal seam */
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
const attr = gl.getAttribLocation(program, "a_pos");
gl.enableVertexAttribArray(attr);
gl.vertexAttribPointer(attr, 2, gl.FLOAT, false, 0, 0);
u_res = gl.getUniformLocation(program, "u_res");
u_time = gl.getUniformLocation(program, "u_time");
width = height = 0;
resize();
return true;
};
let raf = 0;
const draw = (time: number) => {
if (!gl || !resize()) return;
gl.uniform1f(u_time, time);
gl.drawArrays(gl.TRIANGLES, 0, 3);
};
const loop = (now: number) => {
raf = requestAnimationFrame(loop);
draw(now / 1000);
};
let visible = false;
const start = () => {
if (dead || !visible || document.hidden || raf) return;
if (!started && !setup()) return; // no WebGL at all — nothing to play
if (motionQuery.matches) {
draw(12.5);
return;
}
raf = requestAnimationFrame(loop);
};
const stop = () => {
if (raf) cancelAnimationFrame(raf);
raf = 0;
};
const io = new IntersectionObserver(
([entry]) => {
visible = entry.isIntersecting;
if (visible) start();
else stop();
},
{ rootMargin: "160px" }
);
io.observe(canvas);
const ro = new ResizeObserver(() => {
if (motionQuery.matches) draw(12.5);
});
ro.observe(canvas);
const onVisibility = () => (document.hidden ? stop() : start());
document.addEventListener("visibilitychange", onVisibility);
const onMotionChange = () => {
if (motionQuery.matches) {
stop();
draw(12.5);
} else {
start();
}
};
motionQuery.addEventListener("change", onMotionChange);
const onContextLost = (e: Event) => {
e.preventDefault();
dead = true;
stop();
};
const onContextRestored = () => {
dead = false;
started = false;
width = height = 0;
start();
};
canvas.addEventListener("webglcontextlost", onContextLost);
canvas.addEventListener("webglcontextrestored", onContextRestored);
return () => {
stop();
ro.disconnect();
io.disconnect();
document.removeEventListener("visibilitychange", onVisibility);
motionQuery.removeEventListener("change", onMotionChange);
canvas.removeEventListener("webglcontextlost", onContextLost);
canvas.removeEventListener("webglcontextrestored", onContextRestored);
if (gl) {
gl.deleteBuffer(buffer);
gl.deleteProgram(program);
gl.getExtension("WEBGL_lose_context")?.loseContext();
}
};
}, []);
return (
<div
className={`aurum-trail-field${className ? ` ${className}` : ""}`}
aria-hidden="true"
style={{ position: "absolute", inset: 0, overflow: "hidden", background: "#050810" }}
>
<canvas ref={canvasRef} style={{ width: "100%", height: "100%", display: "block" }} />
</div>
);
}Custom work
Need one that isn't in the catalogue?
Describe what you're after and I'll reply by email — no promise on turnaround yet, this is a new channel, not a service with a set price or queue.
Fardin Omor Afnan
Reads and answers every request himself