A lighter-weight LLM coding experiment

Simon Willison recently demonstrated how an LLM can be used to build a complete, interactive CSS box-shadow generator. His example was compelling, but the resulting tool shipped with React and JSX — nearly 3 MiB of dependencies for what is fundamentally a small HTML + JavaScript page.

That overhead seemed unnecessary, so I ran a similar experiment with ChatGPT 4o, asking it to build the same kind of tool without any dependencies. The model went straight for a dependency-free approach, so no course correction was needed. The result is deployed at eliben.org/box-shadow-tool:

Screenshot of box shadow tool

Prompting the tool into shape

The full exchange is available as a shared transcript, but the prompts were short and direct. The first one established the core objective:

CSS for a slight box shadow, build me a tool that helps me twiddle settings and preview them and copy and paste out the CSS

The initial output worked, but the layout was underwhelming. The next two prompts pushed on presentation:

Yes, make the tool itself look a bit better with some CSS so it's all centered on the screen and there's enough space for the preview box
the container has to be wider so all the text and sliders fix nicely, and there's still not enough space for the shadows of the preview box to show without overlapping with other elements

Once spacing and alignment felt right, I asked for the copy-to-clipboard action that was in Simon's demo:

this looks better; now add a nice-looking button at the bottom that copies the resulting css code to the clipboard

VSCode flagged the clipboard implementation as deprecated, so one more prompt dealt with that:

it seems like "document.execCommand('copy')" is deprecated; is there a more accepted way to do this?

That produced the final version, which you can inspect via view-source on the live demo.

What the exercise showed

The whole process was quick — noticeably quicker than writing the tool by hand, even though the task is trivial for an experienced developer. Output quality was acceptable: alignment and spacing weren't pixel-perfect, but they were good enough that a human would take over only for final polish.

The more interesting observation was stability. Throughout the conversation, the model only touched the parts I asked it to change; everything else stayed intact. That kind of consistency is something that has been historically unreliable with LLM outputs, but it held up well here for code generation and iterative refinement.

For a small, self-contained tool, the no-dependency path turned out to be both feasible and efficient — no bundler, no runtime, just a few dozen lines of HTML and JavaScript.