Skip to content
Search

HTML:Tools

lastmod 2025-12-15created 2025-12-151 edits

Small web tools that bundle JavaScript and CSS into a single HTML file and run immediately

About

  • A summary of recurring design patterns, based on experience building HTML tools that bundle HTML, JavaScript, and CSS into one file
  • Explains, through concrete examples, how the more than 150 small tools built over 2 years are actually made and maintained
  • A no-build-step structure and use of CDNs naturally lead to a copy-and-paste-based development flow
  • Extends what is possible with browser features alone, from URLs, localStorage, opening files, and downloads to Pyodide and WebAssembly
  • Recording prompts and results and recombining existing tools strengthens a flow in which the tool collection itself becomes a development foundation

The HTML tools concept and examples

  • Small web tools that bundle JavaScript and CSS into a single HTML file and run immediately are called HTML tools
  • More than 150 built over the past 2 years, mostly made of code written by LLMs
  • Representative examples
    • svg-render: converts SVG code to PNG/JPEG images
    • pypi-changelog: generates a diff of changes between PyPI package releases
    • bluesky-thread: displays Bluesky discussion threads as a nested structure
  • The full collection of tools is available at tools.simonwillison.net, and a monthly view shows how they were built over time
  • Most tools are published together with their GitHub source and a record of the prompt or transcript

Basic structure of an HTML tool

  • A single HTML file with JavaScript and CSS inline
  • Avoids React, which requires a JSX build, making copying and redistribution simple
  • Needed libraries are loaded directly from CDNs such as CDNjs or jsDelivr, and dependencies are kept to a minimum
  • Keeps code to a few hundred lines to lower the maintenance burden and keep it quick for LLMs to read and modify

Prototyping with Canvas and Artifacts

  • Uses ChatGPT Canvas, Claude Artifacts, and Gemini Canvas to run HTML tools immediately and shape their initial form
  • Adding a “No React” condition produces code that works right away without a build step
  • Example: paste JSON and convert it to YAML
    • ChatGPT Canvas result: JSON to YAML (ChatGPT), full conversation
    • Claude Artifact result: JSON to YAML (Claude), full conversation
    • Gemini Canvas result: JSON to YAML (Gemini), full conversation

Switching to coding agents when things get more complex

  • With Claude Code or Codex CLI, repetitive work including browser testing with Playwright and the like can be automated
  • For more complex tools (e.g., the Bluesky thread viewer), “upgrades” to these agents are used
  • Tools are added and updated by creating PRs directly against the simonw/tools repository
    • Repository: github.com/simonw/tools
    • Actual PR history: list of closed PRs
  • The workflow with a web-based agent can be seen in a video of using Claude Code for web

CDN-based dependency management

  • Additional libraries are loaded from CDNs
  • LLM Artifacts/Canvas have a CDN allow-list, so an instruction like “use PDF.js” is enough to get the URL set up
  • When needed, find the URL on cdnjs or jsDelivr and paste it into the chat
  • Works as a single HTML file with no npm install or build process
    • npm plus a build step reduces the productivity of quickly hacking on and self-hosting individual tools
  • Versions are included in CDN URLs, keeping things reproducible over the long term

External static hosting

  • Hosting inside LLM platforms has many sandbox restrictions, sometimes blocking loading data/images from external URLs or external links
  • In terms of user experience, warning messages, extra loading, and platform promotion can get in the way
  • The “No React + CDN” combination makes it easy to put tools anywhere without a build
  • Uploading an HTML file to GitHub Pages makes it immediately accessible at a fixed URL
    • GitHub Pages guide: docs.github.com/pages
  • Most tools are managed in the simonw/tools repo and served at tools.simonwillison.net

Copy-and-paste-centric input and output

  • Many tools use, as their core mechanism, transforming pasted input and copying it back to the clipboard
  • Copy and paste is awkward on mobile, so a “Copy to clipboard” button is often added
  • The OS clipboard can hold multiple formats at once, and this “rich” data is also accessible from the JavaScript paste event
  • Representative tools
    • hacker-news-thread-export: converts HN threads into text for LLM input
    • paste-rich-text: extracts the HTML of pasted rich text
    • alt-text-extractor: extracts alt text after pasting images

Debugging tools

  • Dedicated tools built to inspect the actual data structures handled in the browser
  • clipboard-viewer: shows all clipboard data, including text, rich text, images, and files
  • Additional tools
    • keyboard-debug
    • cors-fetch
    • exif

Storing state in the URL

  • A lot of state can be stored in the URL even without a server DB
  • This pattern is preferred for tools meant to be bookmarked or shared
  • icon-editor: preserves the 24×24 icon editing state directly in the URL

Using localStorage

  • localStorage is a browser API that persistently stores data on the user's device without exposing it to the server
  • Used to store large state that is hard to fit in a URL, or secrets such as API keys, to avoid the risk of exposure in a static host's server logs
  • word-counter: automatically saves text being written
  • render-markdown: keeps content while writing Markdown
  • haiku: stores the API key in localStorage and generates haiku based on webcam images

Using CORS-enabled APIs

  • CORS (Cross-origin resource sharing) is a mechanism that controls whether browser JavaScript can call APIs on other domains
  • APIs with open CORS headers are valuable resources for HTML tools, and worth collecting into a list over time
  • Uses iNaturalist, PyPI, GitHub (public repo content can be accessed anonymously via raw.githubusercontent.com), Bluesky, Mastodon, and more
  • Example tools
    • species-observation-map
    • zip-wheel-explorer
    • github-issue-to-markdown
    • terminal-to-html
    • bluesky-quote-finder

Calling LLM APIs directly

  • Calls the OpenAI, Anthropic, and Gemini JSON APIs directly from the browser via CORS
  • Embedding API keys in HTML risks theft and charges, so a “secrets pattern” that stores them in localStorage is used
  • In terms of user experience, getting and pasting an API key adds a lot of friction, but it works
  • Example tools
    • openai-audio-output
    • gemini-bbox

Don't be afraid of opening files

  • With <input type="file">, files can be read and used directly in the browser without uploading them to a server
  • ocr: uses PDF.js and Tesseract.js to turn PDFs into page images and performs OCR in the browser
  • social-media-cropper: after opening/pasting an image, supports cropping to social media ratios (e.g., Twitter/LinkedIn 2:1, Substack 1.4:1)
  • ffmpeg-crop: generates ffmpeg commands for cropping video

Offering downloadable files

  • Files can be generated in the browser and offered as downloads without a server
  • The JavaScript ecosystem has libraries for generating many formats
  • Example tools
    • svg-render: renders SVG and offers PNG/JPEG downloads
    • social-media-cropper: offers downloads of cropped images
    • open-sauce-2025: builds a schedule and offers an ICS file download that can be added to a calendar

Pyodide and WebAssembly

  • Pyodide: a distribution of Python compiled to WebAssembly that runs in the browser
  • It loads cleanly from a CDN, so there is no reason not to use it in HTML tools
  • Additional pure-Python packages from PyPI can be loaded via CORS through micropip
  • Example tools
    • pyodide-bar-chart
    • numpy-pyodide-lab
    • apsw-query

Going further with WebAssembly

  • Pyodide is made possible by WebAssembly, which also lets software written in other languages be loaded in the browser
  • Squoosh.app provides several image compression libraries in the browser
  • Example tools
    • ocr : Tesseract.js uses a WebAssembly port of the existing Tesseract OCR engine
    • sloccount**: ports David Wheeler's SLOCCount utility, written in Perl and C, to the browser. Detailed write-up.
    • micropython** : @micropython/micropython-webassembly-pyscript

Recombining previous tools

  • Another benefit is that with a single public collection of more than 100 tools, LLMs can easily recombine them
  • Sometimes previous tools are copied into the context; with coding agents, they are referenced by name or the agent is asked to search for examples
  • The source code of a working tool serves as documentation, including usage patterns for editing libraries, and raises the LLM's chance of success
  • Full record of how pypi-changelog was built: prompt transcript
    • The prompt instructed it to look at the “pypi package explorer” tool, read the zip-wheel-explorer source, and build a new tool that fetches wheels via the PyPI API, renders a diff between versions, and provides a Copy button
  • See also Running OCR in the browser

Recording prompts and transcripts

  • A habit of saving and publishing LLM usage records helps you improve your own skill at using them
  • For tools built on chat-based LLM platforms, the share feature is used as the recording method
  • When using agents such as Claude Code or Codex CLI, the full terminal transcript is copied, converted to HTML with terminal-to-html, and shared as a Gist
  • When saving a finished tool to the repo, a link to the transcript is included in the commit message - collection of records: tools.simonwillison.net/colophon

Wrap-up

  • Exploring LLMs and HTML tools this way over the past year and a half has been very enjoyable, and greatly helped in understanding what can be built with HTML and what LLMs can do
  • To start your own tool collection, just create a GitHub repo, enable GitHub Pages, and copy in .html files
  • As a bonus, a link to the transcript of adding screenshots to this post using Claude Code and shot-scraper is provided
    • Claude Code + shot-scraper transcript

See also

Favorite site

author Zer0 sitemap