Add a tool

A tool is one folder with one index.html in it. There is no build step, no framework and no bundler — write HTML, CSS and JavaScript, commit, push, and Cloudflare deploys it.

1. Scaffold the folder

npm run new-tool -- slug-of-my-tool

That copies public/tools/_template/ to public/tools/slug-of-my-tool/. Copying the folder by hand works just as well.

2. Register it

Add an entry to the tools array in public/assets/tools.js so it appears on the landing page and gets its title and description:

{
  slug: "slug-of-my-tool",
  name: "My Tool",
  description: "One sentence about what it does.",
  icon: "#",
  tags: ["text", "developer"],
  added: "2026-09-04",
}

3. Write the tool

Put your interface inside <main id="tool">. The shared script adds the header, the page title, the privacy notice and the footer around it:

<link rel="stylesheet" href="/assets/styles.css">
<main id="tool">
  <!-- your UI -->
</main>
<script type="module" src="/assets/tool-shell.js"></script>
<script type="module" src="./tool.js"></script>

Reuse the shared classes — .panel, .field, .row, .stats, .status, button.primary — so every tool looks like part of the same site. Run npm run dev to preview locally.

The rules every tool must follow

How this is checked

npm test scans public/ for the forbidden APIs and for off-origin URLs, and fails if it finds any. The Content Security Policy in public/_headers blocks them again at runtime, in the visitor's browser, even if something slips past review. Neither check replaces reading the diff.