
grids flatten photographs. that's not neutral. it's a choice, and most portfolio sites make it without thinking.
masonry layouts optimize for density. carousels optimize for engagement. neither optimizes for what photographs actually do: create relationships with the images around them.
a panorama next to a portrait creates rhythm. a horizon that continues across two frames creates continuity. the space between shots matters as much as the shots.
Everything visible at once
no slideshow. no pagination. every photograph on one wall, the way you'd hang a show.
large formats anchor the composition. smaller work fills the gaps. the algorithm places boulders first, then sand. constrained elements claim their space before flexible ones settle around them.
artCompiler.json
each image ships with metadata. which crop ratios work. where the focal point lives. how much the layout can stretch it.
{
"EX6A9822": {
"crops": {
"1:1": { "x": 0.5, "y": 0.4 },
"2:1": { "x": 0.5, "y": 0.3 },
"1:2": null
},
"horizonLine": 0.35,
"elasticity": 0.7
}
}the engine scores placements. +150 when adjacent horizons align. penalties for vertical seams that break flow. visual weight balanced across the composition. fifty metrics, one score.
The preloader
stars that breathe. orbital drift with spring physics. responds to your cursor.
while you watch, twenty concurrent fetches pull every image variant into cache. the calm is functional.
Panoramas
two transform layers. outer layer drifts automatically, ken burns style. inner layer responds to drag.
nested CSS transforms compose naturally. no state synchronization, no fighting the browser. just math.
drag to pan · nested transforms stack naturally
function seededRandom(seed: number) {
const m = 2147483647;
const a = 1103515245;
const c = 12345;
let state = seed;
return () => {
state = (a * state + c) % m;
return state / m;
};
}
const layout = seededRandom(hashSession(sessionId));Every refresh different
same photographs, new composition. the session ID seeds the random number generator. deterministic chaos.
share a link and they see what you saw. refresh to discover a different arrangement.
every refresh tells a different story.