My tool collection [0] is inspired by yours, with a handful of differences. I'm only at 53 tools at the moment.
What I did differently:
Hosted on Cloudflare Pages. This gives you preview URLs for pull requests out the box. This might be possible with Github Pages but I haven't checked. I've used Vercel for similar projects in the past. Cloudflare seems to have the odd failed build that needs a kick from their dashboard.
Some tools can make use of Workers/Functions for backend processing and secrets. I try to keep these to a minimum but they're occasionally useful.
I have an AGENTS.md that's updated with a Github action to automatically pull in Claude-style Skills from the .skills directory. I blogged about this pattern and am still waiting for a standard to evolve [2].
I have a base stylesheet that I instruct agents to pull in. This gives a bit of consistency and also let's them use Tailwind, which they'd seem to love.
[0] https://tools.dave.engineer/
One problem I solved with this was a packer needed to scan a few (10-40) ids into his barcode scanner. It was not enough where pulling up their bulk-id-uploader program but also too tedious to go to some "number to barcode" website.
Turns out, barcodes can be made from a google font!
https://fonts.google.com/specimen/Libre+Barcode+39
You can just display a number using that font. Then hooked up a for-loop that's progressed by pressing the space bar: paste in IDs, scan first, space, scan next, repeat.
For anyone interested, to achieve synchronization I basically just use the https://github.com/google/diff-match-patch lib and save the patches in a db for each version with a version id. Then there's a generic JS file that I inject to uploaded HTML files that monkey patches the localstorage methods and optimistically updates the localstorage at the same time sending the diff to the server to save to the db.
The CDN approach works, but I don't love depending on some third-party service just so your app continues working. Instead, I like using vite with vite-plugin-singlefile. This lets you package your JS and CSS into a single HTML: https://www.npmjs.com/package/vite-plugin-singlefile
Personal tools seem like a reasonable place for happy path vibecoding given small blast radius and LLMs can do that sort of static page in front of python backend really well.
I've also been surprised how much active learning I'm doing despite specifically not look at code. Between the need to spec things out carefully (plan.md) and fast iteration loop it's been a huge boost. Having the LLM look at a plan.md and suggest improvements has lead to a lot of "oh I didn't think about that" learning on architecture and user requirements link.
Presumably much of that learning boost is because I'm a hobbyist tier programmer, guessing professionals wouldn't experience the same since they learned this via manual coding trial & error over years.
I found out about a new Python HTML parsing library - https://github.com/EmilStenstrom/justhtml - and wanted to try it out but I'm out without my laptop. So I had Claude Code for web build me a playground interface for trying it out: https://tools.simonwillison.net/justhtml
It loads the Python library using Pyodide and lets you try it out with a simple HTML UI.
The prompts I used are in this PR: https://github.com/simonw/tools/pull/156
I don't have a lot of public examples of this, but here's a larger project where I used this strategy for a relatively large app that has TypeScript annotations for easy VSCode use, Tailwind for design, and it even loads in huge libraries like the Monaco code editor etc, and it all just works quite well 100% statically:
HTML file: https://github.com/blixt/go-gittyup/blob/main/static/index.h...
Main entrypoint file: https://github.com/blixt/go-gittyup/blob/main/static/main.js
More recently, I've found a lot of benefit from using the extended thinking mode in GPT-5 and -5.1. It tends to provide a fully functional and complete result from a zero-shot prompt. It's as close as I've gotten to pair programming with a (significantly) more experienced coder.
One functional example of that (with 30-50% of my own coding, reprompting and reviews) is my OntoGSN [1] research prototype. After a couple of weeks of work, it can handle different integration, reasoning and extension needs of people working in assurance, at least based on how I understood them. It's an example of a human-AI collab that I'm particularly proud of.
[1] Playground at w3id.org/OntoGSN/
I've also been using LLMs to create and maintain a "work assist" Chrome extension that I load unpacked from a local directory. Whenever I notice a minor pain point, I get the LLM to quickly implement a remedy. For example, I usually have several browser tabs open for Jira, and they all have the same company logo as the favicon, so my Chrome extension changes the favicon to be the issue type icon (e.g. Bug, Story, etc) when the page loads. It saves a little time when I'm looking for a specific ticket I've already opened.
This really showcases the power of the single page apps and why web will be always ahead of native for this kind of Swiss Army Knife tools.
With LLMs, it gets ridiculously easy to “develop” (generate) those too.
One pattern I've settled into: keeping tools under ~200 lines of JS total. Past that threshold I start losing the ability to hold the whole thing in my head, and the main benefit of these tools is that you can open them in a text editor and understand everything immediately.
The CORS limitation that xnx mentions is real though. I've worked around it a few times by having tools accept paste-from-clipboard instead of fetching URLs directly. Less elegant but it keeps the tool self-contained and avoids the proxy problem simonw mentioned.
One tool I'd really like to see in this format is a simple "turn the background of this PNG to transparent". Models still refuse to follow the instruction to create transparent backgrounds for logos they create, and I often have to look for other tools doing this as post-processing.
It's possible that this is too complicated for the "few hundred lines of js" code envelope, though.
- Shell scripts, AppleScripts, etc. that I trigger from Alfred
- Obsidian plugins
- The occasional Emacs Lisp function
They serve a similar purpose for me as OP's HTML Tools, in the sense that they let me automate a small part of my workflow that I wouldn't otherwise have automated. If I have to choose between writing AppleScript and just doing something manually, I'll pick doing something manually 100% of the time. But if I can just ask an LLM to write the automation for me and then test it in a bunch of different scenarios, the choice becomes much easier.
After reading this post, I really want to try moving some of my automations to the web. Using HTML/JS/CSS for some of these tools will let me solve a whole different set of problems. E.g. I could more easily build automations for the non-techy folks in my family instead of just keeping them to myself.
LLMs are generating app for an idea that can fit in few hundred lines of html/js. Had an idea that what if brushes were dithered in a painting tool and made a dithered painting tool. https://github.com/SMUsamaShah/dither-painter
These tools and code are ephemeral though. You don't need to use mine for example. Just ask the LLM of the time to implement the idea and in most cases it will work fine.
Reviewing data in Excel is painful, especially when answers are in HTML or Markdown, because you don’t get proper rendering. Building small, custom tools that reduce the friction of reviewing data makes life much easier and more pleasant. These days, I use Claude Code for Web to build most of these apps, and they are deployed on Vercel.
Things like styling buttons, responsiveness, and so on are better solved once.
A good rule of thumb is: if the shared CSS fails to load, page still fully works but it might be uglier (weird fonts, etc). That's a reasonable rule for proper isolation (tools remain simple to understand, code remains reusable, etc).
I love the idea of self-contained tools, but you're already using CDNs. Having a shared CSS wouldn't hurt and actually make the tools better.
I would go as far as having a shared JS too (same idea, works if it doesn't load).
That's essentially what I did in https://alganet.github.io/spiral/ (also vibe coded).
Each spiral is mostly independent. You can go ahead and delete the shared CSS from the <head>, they still work and don't break funcionality. However, by having the shared CSS I made them consistent, made them friendly to phone users and so on.
Not sure why, but the moment the file is split into files and subfolders, coding agents tend to do a lot more changes that what is absolutely necessary. That way a single html file wins!
I wonder if packaging the results as web components would be the next logical step.
No. You can vendor these scripts & host them 1st party so you aren’t leaking data to these CDNs or risk users not actually getting the scripts. It isn’t like CDNs give you a performance boost anymore.
As if your steady stream of learning-in-public experiments and insights weren't generous enough. Seriously, massive kudos for sharing all the details.
it does something like this
and connects through BLE
They have a library of sample apps you can edit but I wish they included the prompts and history to build each since I generally can’t get large apps to work - after a while the I’ll just produces more bugs as complexity grows. But I’m also a bad vibe coder and never read the code so entirely my fault :)
I have a Vue3 started template I host at https://http://vue-template.spaghet.me/ and all I have to do is curl and I'm ready to go.
Showcase:
https://timer.spaghet.me/ https://colors.spaghet.me/ https://box.spaghet.me/ https://talk.spaghet.me/ https://farming.ope.cool https://stitch.ope.cool https://draw.ope.cool https://walz.ope.cool
I list them at https://client-side.app/
Create PDFs from images, a Wordle hint/solver, or a classic DVD screensaver. Lots of stuff.
I use indexedDB for it and will use sqlite if I start to get more serious data needs.
I haven’t found too many issues with loading React and Babel from a CDN. I find React easier to read than straight HTML/JS. I find it more annoying to code in but seeing what state is needed in what components is a pleasant reading experience for me with single file tools.
I tend to make them as Python servers which serve plain html/js/css with web components. I know this is a bit more complicated than just having a single html file with inline js and css, but the tools I made were a bit too complicated for the LLMs to get just right, and separating out the logic into separate js files as web components made it easy for me to fix the logic myself. I also deliberately prompted the LLMs to avoid React because adding I didn't want to need a build step.
The only one I actually still use is the TODO app I made: https://github.com/cooljoseph1/todo-app It stores everything in a JSON file, and you can have multiple TODO lists at once by specifying that JSON file when you launch it.
also sad, that XHTML was abandoned.