Why I built it
3D on the web usually means WebGL and a 3D library. Yet plain CSS can do a surprising amount on its own: it can turn, fold, stack and light flat boxes in real 3D. It is just hard to learn from articles, because the tricks only make sense once you see them move and can poke at them.
So I wanted a lab, not a list of snippets. Every model shows what it is, explains how it works in a few steps, and hands you the code in an editor, so you can change a number and watch the model change. It is free, with no sign-up, for anyone who learns by playing: people learning CSS, designers curious about 3D, and developers looking for something interesting to put on a page.
From one sentence to 135 models
At 13:38 on a Friday in September I typed one long sentence into Claude. I wanted a new project that would "demonstrate all possible 3D effects with SCSS", with and without JavaScript, as a gallery with filters and search. Six minutes later I added the part that mattered most: make it look amazing, give every example code people can copy, because "it is more like an education app".
Nineteen minutes after the first message, the first commit held 21 3D models, and two minutes later they were live on the web. By 10:33 the next morning there were 135, and I had slept in between. At 12:18 the last of them went live with its own video, 22 hours and 40 minutes after the first message.
It came together in about a day. This is the honest account of how. As with J.A.R.V.I.S. and Self-Aware Writing, I went back through the session logs and the full git history, so the numbers are counted, not remembered. My own messages are quoted with the typos fixed; the wording is mine.
What CSS 3D Lab is
A free gallery of 3D models built with CSS: cubes, gems, a phone, a payment card, a twisting puzzle cube, loaders, text effects, whole scenes, and ten neon charts drawn from JSON data. There is no WebGL and no 3D library. 93 of the models are pure CSS. In the other 42, JavaScript only feeds numbers in, and CSS still does all the drawing.
Every model runs live next to a "how it works" in three to five steps and copy-paste code: a standalone HTML and CSS snippet with no build step. The build refuses to ship a model without one. The code window is an editor, so you can change the snippet and watch the model change. Each model also has its own page, an embed, a share image, a vertical download video and a print button that turns it into an art sheet.
It is built with Vite, TypeScript and Sass, with no UI framework. It installs as an app, has no accounts and no ads, counts visits without cookies, and has a coffee link instead of a paywall. The code is open source under MIT.
How it happened
Friday 13:38: one sentence. The first commit landed at 13:57 with 21 models. At 14:19 I asked for 50, and whether 50 would make the app lag. They wouldn't: a model only exists in the page while its card is near the screen. 50 models were live at 14:36.
Friday afternoon: bugs you only find with a mouse. The rolling button flickered when I hovered it. The button that rolled was also the thing being hovered, so as it turned, it rolled out from under the pointer. Rounded dice showed daylight where three corners meet. On the ripple flip, about 40% of the points Claude sampled over the tiles hit an invisible container instead, so the cursor was wrong and clicks did nothing. Each fix became a rule in a short guide for adding models. It now has eleven rules under the heading "these were all real bugs".
Friday afternoon: the paid version that wasn't. At 15:36 I started planning a Pro tier: groups of premium models, a lifetime price, colour palettes and three intensities. Claude built a private repository, a theme system and five components. Then I asked the real question: "do you think it is actually worth making this for sale? Anyone can build it with AI now anyway". Claude agreed with the doubt. It had built those five components in minutes, and "nobody will pay for a snippet". By 17:03 Pro was parked, to be revisited only "once we reach an amount of engagement". The plan became simpler: a free site, a coffee link, and as many specific, searchable models as possible. I also skipped buying a domain and put the lab on a subdomain of my own site.
Friday evening: videos, and a hundred models. At 18:35 I asked for GIF and MP4 export on the site. It was built at 18:45, and at 18:49 I asked whether we really needed it. It was gone by 18:54. At 19:37 I came back with the real need: short videos for Reels and YouTube Shorts. So the videos are filmed from the built site, frame by frame, and every model gets a vertical download clip. The clips live on a GitHub release, not in the site. A button only appears once its file really exists, it shows the real file size, and the deploy fails rather than publish a dead button.
Meanwhile five Claude Fable 5.1 agents were building 50 more models in parallel. At 19:50 Fable hit its limit mid-build. I wrote: "ok, Fable 5.1 reached the limit, so Opus, your turn to continue". Claude Opus 5 took over, three helper agents finished the half-built models, two Claude Sonnet 5 runs wrote their snippets, and 100 models were committed at 20:27.
Friday 21:54: the Codex detour. Claude's limit came back at 21:39, with a reset at 23:30. I opened OpenAI's Codex: "ok, I got stuck with Claude Code on the limit, maybe you can continue the work". It read the project and checked all 100 models. Then I asked for a few small things: centre the controls, improve the share image. It read one of my rushed messages as a request to redesign the home page's hero, and did. "hey, why did you change the hero? I want the cube back, what the hell are you doing". Two minutes later I asked it to roll everything back. It did, explained that it had merged several loose requests into one redesign, and recommended waiting for Claude. Codex made no commits.
Friday 23:32 to Saturday 04:09: the night shift. Claude came back and published download videos for all 100 models. At 00:37 five agents started 25 new models in parallel, and at 01:26 there were 125. The logo took most of an hour of saying no: "still not hitting me, try something different", then "I still like the original more". We went back to the single cube, now in tinted glass. The glow in the background's corners went from 60% of the screen to 73% and then 66%, "between the last two", in six minutes.
At 02:35 I noticed the word "demo" everywhere: "it is not a demo anymore". Visible text now says effects, and pages moved to /models/, with the old addresses forwarding. Then came search: a page per model and per group, a sitemap with each page's real last-changed date, and a favicon that search engines can find. At 03:56 I asked: "ok, so all done, can I go to sleep or is something still unfinished".
Saturday 09:02: charts, print and edges. I started with "ok, so we created this project yesterday and it is amazing, I love it", and one complaint: the speaker model's back edge wasn't smooth. Then a bigger question: should I build a 3D chart library, like Recharts but in 3D? Claude advised against a separate library. I decided to keep the lab simple and show charts inside it instead: ten 3D neon charts, each drawn from a small JSON file, the shape an API usually returns. Claude built the first three by 10:03, and seven helper agents built the other seven by 10:33.
Then print. I asked whether a model could print "as art itself", without the credits. Now every model prints as a single art sheet, on the stage's own dark or light backdrop. Two print bugs followed. A greeting card printed its inside mirrored on top of its front, because Chrome ignores hidden back faces when it prints. And the print always started the model from its first frame, not the pose on screen. Claude suggested using the existing pause button. I wanted a switch that holds any model's hover look, and asked for one on every model. Both shipped: Pause, and Hold hover (Hold tap on phones), so any pose can be printed.
Saturday late morning: the usage runs low. At 10:32 I sent Claude a screenshot of my limits and a warning: "also to note, we are running out of the weekly usage, so don’t waste time". At 10:58 another: "also keep an eye on the usage, it is getting low". On phones the code window got a one-row header and wrapped lines. The model dialog became only as tall as its content, centred when it fits. I asked for videos with a transparent background, and Claude tested an animated WebP: it works, but the staircase came out at 7.2 MB at 720×1280, against 3.2 MB for its full-size MP4, so it stays a test for now. At 12:18, with 33 videos refilmed to match the day's fixes, everything was pushed, and all 135 models were live, each with its video.
The edge that wasn't one bug
The last hour went into edges. "the payment card looks so smooth compared to the business card with its glittering sides". Why did one sparkle and not the other?
The payment card only tilts about 15° toward the pointer. The business card flips all the way round, so for a moment it is exactly side-on. At that moment every thin part of it, the faces, the 4px edge and the raised print, is squeezed into lines narrower than a pixel. A browser can't draw those evenly, so they break into dashes. The fix is the same every time: draw an edge with surfaces that face the viewer, not with ones seen side-on. That fixed the speaker and the dice. One pass applied it to twelve more models, and a helper agent fixed eight more whose thin edges broke at card size. The business card was rebuilt: at rest its edge is drawn by slabs that face you, the side walls only fade in mid-flip, and a faint light rim now outlines it like the payment card.
What remained is a real limit. When a browser draws live 3D from CSS, the graphics card doesn't smooth the outer edges of turned faces the way a rendered image or video does, and no CSS setting turns it on. Our videos look perfectly smooth because they are rendered at double size and scaled down. The live models can't do that without going blurry. On a sharp screen, a Mac, most phones or Windows at 150%, the steps mostly vanish. On a regular monitor at 100% you can see them.
Claude couldn't see the problem at all: its test browser has no graphics card doing that smoothing. So it built a switch into the page, I compared both versions on my screen, and I reported what I saw. The rule we ended with: dashed or broken edges are a bug, so send them in. Slight steps on a slanted outline are the browser's limit, and we say so.
What we got wrong
- The hover target moved. Anything you hover now stays still, and only a part inside it moves.
- Solid shapes weren't solid. Rounded boxes showed daylight at the corners, and the hero cube did too, twice.
- GIF and MP4 export went into the site and came out nine minutes later.
- A paid tier got a private repository, a theme system and five components before we asked whether anyone would pay.
- Asked for small changes, Codex misread a rushed message and redesigned the hero. Everything it did was rolled back.
- The first videos and the full-screen view were soft, because the model was stretched instead of drawn bigger.
- Printing ignored hidden back faces, so "OPEN ME" came out backwards on top of the front.
- A print showed the model's first frame, not the pose you chose.
- The model dialog filled the whole screen height even when its content was short.
- The business card's edges glittered whenever it turned side-on.
Most of these were found the same way: I used the site, took a screenshot and said what looked wrong. I sent 194 screenshots in less than a day.
Who did what
Claude Code did the building. Claude Fable 5.1 ran the first six hours and made 35 commits. Claude Opus 5 took over when Fable hit its limit and made the other 68. Claude replied 3,123 times and made 3,849 tool calls: 1,801 commands, 606 file edits and 411 actions in a browser. 1,407 of those replies came from 26 helper agents. Most of them built models in parallel batches; one researched where to post the launch on Reddit. That was about 16 hours of active work.
Codex had one evening: 16 messages, 7 screenshots, 67 tool calls and about half an hour. It checked all 100 models, then misread me and redesigned the hero, and I rolled it back. It left no commits.

Less than a day, counted from git and the session logs: Claude Code, Codex and me, and how the gallery grew.
Alt text · 394 characters
CSS 3D Lab by the numbers, 18 – 19 Sep 2026: 135 models (93 pure CSS, 42 CSS + JS), 103 commits, 22h 40m from first message to last commit. Claude Code: 103 commits (35 Fable 5.1, 68 Opus 5), 3,123 replies, 3,849 tool calls, about 16 hours active. Codex: 16 messages, 67 tool calls, no commits. Me: 288 messages, typically 22 words, and 194 screenshots. Models over time: 21, 50, 100, 125, 135.
My part was deciding. I sent 288 messages, and a typical one was 22 words. More than a hundred of them went in while Claude was still working on the last one. I stopped it mid-task five times. I decided what the lab is for: learning, with code people can use. I decided what it is not, a shop, at least not yet. And I said what looked wrong, from a flickering button to a background glow a few percent too wide.
Treat the numbers as a record, not a benchmark. The models worked on different hours and different jobs.
What it cost
The lab costs nothing to run. GitHub Pages hosts it, the videos sit on a free GitHub release, the address is a subdomain of a domain I already had, and the analytics are free.
The cost was the Claude subscription, and the limits shaped the day. Claude's limit message appeared at 18:00, 19:50 and 21:39 on Friday. On Saturday morning Claude reported my weekly limit at 96%, then 97%, and I kept warning it to spend the rest carefully. That allowance is shared with everything else I built that week. It was just enough: everything was pushed at 12:18, and the 135 videos, 189 MB in all, sit on the release.
What I would tell someone starting
- One sentence is enough to start. Typos and all. The first 21 models were live 21 minutes later.
- Turn every bug into a rule. Every batch of helper agents was told to read the guide first, so a bug fixed once stayed fixed.
- Ask "will it lag?" early. One question at minute 41 decided how every model is loaded.
- Don't build the shop before the visitors. An honest "is it worth it?" saved me from a product nobody had asked for.
- Only show a button when the thing behind it exists. Real file sizes, and a deploy that fails instead of lying.
- Know a bug from a limit. Fix the first, and say the second out loud.
- One tool per job at a time. Two assistants on one half-finished task made a mess. The second one's best advice was to wait for the first.
- Use it like a user. Screenshots of real screens found almost everything the checks couldn't.
In one paragraph
In less than a day, with a night's sleep in the middle, one person and Claude went from a single sentence to 135 live CSS 3D models, each with its explanation, its code and its video, in 103 commits. Claude wrote almost every line, and its helper agents built most of the models in parallel. The shape of the thing came from a long run of small human calls: make it for learning, don't sell it yet, that glow is too wide, keep the original cube, this edge glitters. The models made building fast. Deciding what to build stayed with me.
Try it at css3dlab.edgarasneverdauskas.com. The code is open source under MIT at github.com/Evirtual/css-3d-lab. Built with Claude Code, Claude Opus 5, Claude Fable 5.1 and Claude Sonnet 5, with a short detour through OpenAI Codex.
