Skip to content
Engineering5 min read

The 3D world that rendered perfectly and was invisible

Four thousand particles, eight morph states, a shader that compiled and a frame loop that ran. The build was green. The page was empty. It cost one screenshot to find.

The homepage is a scroll story over a single particle system: about four thousand points that morph between eight precomputed formations as you move down the page.

It took a while to build. The shader compiled. The frame loop ran at sixty frames per second. The morph weights interpolated exactly as intended. The build was green, the tests passed, the console was clean.

The page was black.

What was actually wrong

The canvas was -z-10, sitting behind the story's container. The container was relative and carried an opaque background.

A relative element with no z-index does not create a stacking context. So the canvas at -z-10 was not painted behind the page — it was painted behind its own parent's background, which is opaque, which is the entire viewport.

The fix is three characters and one deletion: the canvas becomes z-0, the panels become relative z-10, and the container carries no background at all.

Why nothing caught it

Consider what would have had to exist to catch this automatically.

A unit test on the world? It was working — every value it produced was correct. A test on the component tree? The elements were all present, in the right order, with the right classes. A visual regression test? There was no previous screenshot to regress against; this was the first version.

The only thing that catches it is a person looking at the page.

Three more from the same session

The screenshots that caught the black page caught three others, and every one of them was invisible to the build.

The reader was one act behind the store. Progress was measured as -rect.top / height, which is the obvious spelling and is off by half a screen. It reported the first act while the reader was looking squarely at the third — so the section being read was the dimmed one, and the world was a state behind the words. Each act now computes its own start and end.

A point of light sat exactly on the Arabic headline. The hero's light source was at the world origin and projected straight through the middle line of the Arabic type. The English happened to miss it, because the English middle line is shorter. Found in the Arabic, by looking at the Arabic.

The vignette multiplied toward black. Which is invisible on a near-black canvas and, on the light setting, ringed the whole hero with a dark halo. It mixes toward the page colour now.

Three of those four are direction- or theme-dependent, and none of them can be found in one screenshot of one language.