Log · Research / Implementation · 2026.09
A three.js Site Built with Claude Code
What two three.js sites built with Claude Code left behind: a line between machine checks and the eye
Two three.js sites built with Claude Code. The constraint that mattered most turned out to be that the assistant cannot see the screen. A record of where the line was drawn between what a machine checks and what only the eye settles.
Glass, twice
The first was the site of a glass art collective, where ribbed glass covers the whole screen. Light runs across the vertical striations, and the colour behind them changes as you read on. It is drawn once into an FBO, then distorted by a shader for refraction and chromatic aberration.

The second was my own site, with a glass rose drawn from an equation blooming at the centre. That one uses the transmission of a physical material in three.js. Neither uses a build tool: ES modules and an importmap, nothing else.

It can write the code; it cannot see the picture
Claude Code writes three.js. Material values, shaders, the sync with scrolling. What it cannot do is judge. It never sees the output, so it can never settle whether the glass looks like glass.
The reverse is also true: there are places where a machine is the more accurate reader. Whether the syntax parses. Whether an exception is thrown at runtime. What pixel an element sits at. Whether anything overflows sideways. Whether a referenced image exists. Faster and surer than counting by eye.
So the first decision was not about features. It was where to draw that line.

Run the machine side in full, every time
Three checks before anything is handed over. Pull the scripts out of the HTML and parse them. Serve the page locally, open it in a browser with no screen, and read the console for exceptions. Take a screenshot. Tens of seconds in total.
It caught real faults. A time calculation went briefly negative, a negative index returned undefined, and the exception stopped the whole frame loop. On screen that reads only as "sometimes it does not move". One line in the console and it is a five-minute fix.
It also missed things. The extraction pattern for the syntax check left out <script type="module">, so the module went unchecked for a long time. And a syntax check does not catch a constant used before its definition. That happened: the script halted entirely and the card list rendered zero items. Parsing and running are not the same thing.
What went wrong on the eye side
Telling the screenless browser to use a width of 390px does not make it so. It lays the page out at its 500px minimum and returns an image cropped to 390. I read an overflow that was not there.
A diagram was once exported at 1600px. The article column is 576px, so it shrank to 0.36 and 11.5px type became 4px. Syntax, coordinates, image existence: every check passes. One look settles it.
The worst was reporting that an animation worked because the difference between frames was large enough. The background had never changed at all. What these share is trusting a region the machine called clean without looking at it.
The glass is the part I always look at myself
Transmission is full of traps. Make the renderer background transparent and the transmission calculation loses the ground it composites against. Only opaque objects enter the transmission buffer, so a panel meant to be seen through the glass shows nothing if it is transparent. Neither prints anything to the console. The only symptom is that it does not appear.
And it cannot be checked on a screenless browser. With the GPU it renders, but the environment light is dark and the colour is not what it is in a real one. Switch to software rendering and transmission stops the thing outright.
So the rose is the one thing I open a browser for, every time. This part is not automated, and that is written down. Unwritten, it stops happening on the day the numbers look good.
What was left
After two of them, what remained was not three.js code but the line itself. On the machine side, fix the procedure and run all of it every time. On the eye side, write down that it is checked by eye.
The line only needs redrawing when something goes wrong.