Josh W. Comeau
banner
joshwcomeau.com
Josh W. Comeau
@joshwcomeau.com
Indie developer and educator. Blogging at http://joshwcomeau.com.
Previously at DigitalOcean, Khan Academy. Taught at Concordia Bootcamps.
He/Him 🌈
In addition to the voxel editor, there’s also a terrain generator: terra.layoutit.com#eJx1l8lyI0cM...

So cool that this is all plain DOM nodes. 🔥
January 12, 2026 at 4:28 PM
Well this is remarkable. 😮

Someone built a 3D voxel engine using plain ol’ DOM nodes, no canvas/webgl. And it’s surprisingly performant, since it culls any faces that aren’t currently visible.

Repo: github.com/LayoutitStud...

There’s even a nifty lil’ editor!
January 12, 2026 at 4:28 PM
The most satisfying part of my job is that I occasionally get messages like this, from folks who were able to land a job in part due to my courses. ❤️
January 10, 2026 at 5:07 PM
What on earth. 😂
December 23, 2025 at 10:24 PM
👀 Working on the third module of my animations course, where we learn to create advanced cursor interactions.

Having fun with eyes. Not creepy at all. 😅
December 18, 2025 at 10:06 PM
I once made the mistake of downloading Microsoft Edge on my mac. I uninstalled it a long time ago, but Microsoft AutoUpdate remains, and every day it asks me if I want to update the AutoUpdate application. 😂

Just figured out how to erase it. Good riddance.
December 17, 2025 at 3:01 PM
This looks OK, but it would be so much more satisfying with more particles. Check out how nice it is with 70 particles instead:
December 9, 2025 at 9:39 PM
For example, suppose we’re building a sparkly "Like" button particle effect. How many particles should we generate?

My approach historically has been to figure out the largest # that will run smoothly on my low-end 2019 Android smartphone. In this case, it’s something like 15:
December 9, 2025 at 9:39 PM
It’s in the article you shared 😄
December 7, 2025 at 12:25 PM
Sounds like `/terminal-setup` is the main solution, but this only works for certain terminals, and Hyper isn’t one of them.

It’s not really Claude Code’s fault; this is sorta the integration nightmare I’d imagine trying to build a full-fledged app that works in any terminal 😅
December 4, 2025 at 6:07 PM
I tried to clarify that I'm talking about the file it just generated for me, but that didn’t work either:
December 4, 2025 at 4:35 PM
It was looking for the file in my active directory. There’s a hidden `.claude` directory in there, so I figured that’s where the dynamically-generated prompt file would be.

But no. It’s here:
December 4, 2025 at 4:35 PM
So, I tell Claude Code to use the prompt I just saved in Cursor.

This is the result:
December 4, 2025 at 4:35 PM
This is already a bit weird; isn’t the whole sales pitch with Claude Code that we *don’t* need to use an IDE anymore? If I’m gonna write the prompt in Cursor, why don’t I just use Cursor’s agent mode?

But anyway, I press the shortcut and a new Cursor file opens:
December 4, 2025 at 4:35 PM
Most of the prompts I send these days include multiple paragraphs, but at least in my terminal, Shift + Enter doesn't work. Instead of adding a newline character, it submits the prompt.

When my prompt spans multiple lines, Claude suggests editing the prompt in my IDE:
December 4, 2025 at 4:35 PM
When it became clear that the AI was stuck, I decided to give it a technical prompt:

> It still isn't correctly misaligned. The problem is that you’re using display: contents. Instead, use CSS subgrid so that a two-column grid structure is passed down to the children

This fixed it, immediately:
November 30, 2025 at 4:31 PM
This was honestly pretty shocking to me. 😅

The tricky thing with this UI is that the features are all different heights (1 to 3 lines of text), and they’re supposed to line up perfectly, so that it’s easy for users to compare the same item across both cards.

Here’s the mockup again, showing this:
November 30, 2025 at 4:31 PM
I gave Gemini this screenshot and described what I wanted in plain English.

It did not go well. 😅

After a dozen prompts and 12 minutes, here’s the closest I got:
November 30, 2025 at 4:31 PM
This weekend, I put this hypothesis to the test. Using the benchmark-topping Gemini Pro 3, I tried to reconstruct the following UI, pretending that I didn’t really know HTML/CSS.
November 30, 2025 at 4:31 PM
🎈 Friendly reminder that my courses are on sale for Black Friday! I’ve gotten a lot of positive feedback about them, including this lovely testimonial just today.

If you live in India, or another country with similar purchasing power, you can combine the Black Friday sale with a regional license. 💸
November 29, 2025 at 10:51 PM
Tools like Cursor or Claude Code make us *feel* more productive, but can we trust that perception?

I added a new blurb to my 2025 post about AI, “The Post-Developer Era”, which digs into a recent study about developer productivity and AI:
November 24, 2025 at 8:35 PM
Coming next week on my blog. ✨
November 22, 2025 at 9:17 PM
Whereas on the blog post page, there's just enough space to leave the blocker sitting just above the content:
November 13, 2025 at 6:15 PM
Right, I couldn't use the same trick on the homepage because in order for this trick to work, I need to be able to "hide" a rectangle above the content, that sits there waiting to follow the header when it reaches that point. There's no space for such a sticky blocker:
November 13, 2025 at 6:15 PM
Thanks for the detailed write-up!

I think I’m missing something, though… It sounds like this optimization is designed to handle the case where `width`/`height` is included in a keyframe definition, but keeps the same value, like this?
November 13, 2025 at 6:07 PM