How Helen Gets Made A making-of, not the live show Watch her live

Court · the 3D website

The 3D website: why a cat livestream has a WebGL room, and what it is made of

helenthecatlive.com is a static site whose home, about and shop pages open a three.js room on desktops and a plain camera frame on phones.

The code for the scene is on the three.js build page; the four pages under this one cover the page shell, the byte ledger, the shop's floor plan and the tests.

Helen, the dilute tortoiseshell the website is built around
The subject. The website exists so that four cameras pointed at her can be shown as one room rather than a grid.
Pick your page — the 3D website
The questionThe page that answers only that
What is the site made of?This page: 25 static pages, a three.js court and shop, a phone shell, one Node process.
How do the shell and the scene share a page?Page architecture.
What does a visitor download?Performance: the byte ledger.
How is the shop laid out?Shop layout in 3D.
How is it tested without a GPU?Quality checks.
How does the court itself run?The three.js court · The 3D shop · The court hub.

Open helenthecatlive.com on a laptop and you are standing in a dark sitting room. There is a velvet chair, a gold-framed painting on each wall, a small tortoiseshell cat on a cushion, and the paintings are not paintings: they are the four public cameras in the real room, refreshing every few seconds. Drag, and the room turns. Click a frame, and you walk up to that camera. Open the same address on a phone and there is no room at all, just the four cameras in a plain frame, because a phone rendering a lit 3D scene is a warm phone with a short battery and a page that stutters. Both of those are the same website, and this section is about how it is built.

The short version: it is a normal static website, twenty-five HTML pages built with Vite, and three of those pages (the home page, the about page and the shop) also load a WebGL scene written against three.js. There is no framework. There is one small Node process behind it that talks to Stripe, to the print service and to the camera proxy, and everything else is files served by Caddy. The three.js build page reads the scene code line by line; the pages under this one cover what that page does not: how the HTML and the scene share a page, what a visitor actually downloads, how a shop is laid out in a room, and how any of it is tested without a graphics card.

Why a cat camera has a room at all

Most live pet cameras are a grid of rectangles. Six feeds, no sense of which is left of which, no idea whether the fountain is across from the bowl or in another house. The court page makes the argument from the physical side: one small room, five reasons for a cat to go somewhere, and the cameras placed where a body would stand. The website is the other half of that argument. If the geography is the product, the page has to have geography, and a grid does not. So the room on the site is the real sitting room, rebuilt: the same walls, the cameras where the cameras are, and a visitor who can turn from the water station and find the food bowl the way they would if they were standing there.

That is the reason for the WebGL. It is not a game and was never meant to look like one. The repository keeps a twelve-point quality bar, and the second point is court, not a game: dark velvet, antique gold, cream type, no neon, no floating health bars. The third is that the live cameras are one screen you switch, not a slideshow on the back wall. The ninth is that a stale or down feed shows as standby and never as a fake live badge. Those are design rules, and they are checked against screenshots.

What the site is made of

The pieces, and where each one runs
PieceWhat it is
Twenty-five HTML pagesPlain files: home, about, shop, checkout, the journal pages, the press kit, the FAQ. Vite builds them all at once and stamps the analytics tags onto each at build time.
The court sceneA three.js room loaded by the home and about pages on desktops only. Four camera textures, a cat mesh, a chair, the paintings. The three.js build page.
The shop roomA second three.js room that shares the renderer and the quality loop with the court, with sixteen products standing on real furniture. The shop layout page and the print-on-demand page.
The journal stagesSmall still-life scenes on the build pages that render once and stop. The page architecture page.
The phone shellEvery page on a phone. No WebGL; the cameras in an HTML frame with the same live JPEGs.
One Node processTakes the bag and prices it, creates the Stripe payment, verifies the webhook, sends the print order, and fronts the camera proxy. Described on the treat page and the hosting page.
CaddyServes the files, compresses the JavaScript and the model files, sets cache lifetimes, and hands /api/* to the Node process.

A visitor on a desktop downloads the page, a few small scripts, then the three.js runtime, then the room, then the cat, then the four camera stills, in that order and with the model deliberately last and at low priority. A visitor on a phone downloads the page, the same small scripts, and the four stills. The numbers for each are on the performance page.

Who built it, and what the models got wrong

  1. Decide what the room is for before you open an editor. The court exists to show four live cameras in the geography of one real room. Every object in it either carries a camera frame, is furniture from the real room, or sells something. If you cannot say what a 3D room does that a page of pictures could not, build the page of pictures.
  2. Ship the plain version first, and keep it. Phones never load the 3D room; they get the same four cameras in an HTML frame. The shop keeps a plain product list under the room. If WebGL fails or takes more than twenty-five seconds, the page swaps to that plain version by itself. The room is a desktop's way of showing the cameras, not the only way.
  3. Build the room from the real room. Measure the sitting room, photograph the walls, and put the four camera viewpoints where the four cameras really are. The court page has the tape-measure half of that.
  4. Put the model in last, and let it fail quietly. The cat mesh loads after the room is standing. If it 404s the standing pose is tried; if that fails the room opens without a cat and says so in the console. The 3D generation section has how the mesh was made and repaired.
  5. Spend the byte budget on what the visitor sees first. The three.js runtime is 176 kB compressed, the cat is 1.99 MB, and the four camera stills are a few tens of kilobytes each and refresh one at a time. The performance page has the whole ledger, desktop and phone.
  6. Test it without a GPU, then look at it with one. A headless check confirms every product is in the shop room and no set dressing is clickable; a screenshot script proves the page boots at two widths. Neither replaces a person dragging the camera on a real laptop. The quality-checks page has both scripts.

What it is not

It is not video. The paintings on the walls are JPEG stills fetched every two to three seconds per camera through a read-only proxy in front of the house's Frigate; the 24/7 video is on YouTube, where the encoding is somebody else's problem. It is not a walkthrough of the house: only the court is modelled, no bedrooms, no people, no desk with the camera controls on it. And it is not embedded here. This site teaches the build; the show is next door, and a copy of it framed in a page would freeze the moment it was pasted.

The four pages under this one: how the HTML and the scene share a page, what a visitor downloads, how the shop is laid out in a room, and how it is tested without a GPU. The scene itself is on the three.js build page; the physical room it copies is the court.