Skip to content
Michael Dohmen edited this page Aug 13, 2026 · 14 revisions
openToolbox logo

openToolbox

Ship a working tool as a single HTML file. No server, no install, no network.

The main way this repo gets used: you don't write code against it — you point an AI agent at it and describe the tool you want. Claude Cowork, Claude Code, or any coding agent that can read a repo and run npm commands all work the same way here, because the whole workflow is designed around one file, AGENTS.md, that tells the agent exactly what to ask and what to change.

This page shows that workflow with real examples. Everything else in this wiki — architecture, the AI assistant feature, security details, how to develop openToolbox itself — is reference material for after you've built something, linked at the bottom.

The workflow, in one sentence

Say what you want tracked. The agent asks a handful of clarifying questions, writes one file (src/domain.js), builds, and hands you a finished HTML file.

You never touch src/app.jsx, the build config, or any of the plumbing. One file goes in, one file comes out.

Example 1 — starting from a one-liner

You, to the agent:

Build me a tool for tracking vendor certificates, based on openToolbox (https://github.com/m-dohmen/openToolbox).

The agent reads AGENTS.md, doesn't have enough detail yet, and asks — in one round, per AGENTS.md's instructions:

  1. What's one record called — singular and plural?
  2. Which fields, and what type each (text / enum / date / number)? For any enum, what values?
  3. Which field is the headline in the list? Which fields belong in the table itself vs. only the detail view?
  4. Any "overdue" or "done" logic — a date that can lapse, a status that closes an item?
  5. Should the AI assistant be switched on for this one? (Ships off either way; you can flip it on later in Settings.)

You answer, in plain language:

A record is a "certificate", plural "certificates". Fields: vendor name, certificate type (ISO 27001, SOC 2, PCI-DSS, other), expiry date, owner (who's tracking it), and a free-text note. Vendor name is the headline. Table should show vendor, type, expiry, owner. It's overdue once expiry has passed. No AI assistant for this one.

The agent writes src/domain.js — roughly:

export const SCHEMA = {
  idField: 'id',
  singular: 'certificate',
  plural: 'certificates',
  titleField: 'vendor',
  list: ['vendor', 'type', 'expiry', 'owner'],
  facets: ['type'],
  search: ['id', 'vendor', 'owner'],
  totalField: null,
  fields: [
    { key: 'vendor', label: 'Vendor', type: 'text', required: true },
    { key: 'type', label: 'Certificate type', type: 'enum',
      values: ['ISO 27001', 'SOC 2', 'PCI-DSS', 'Other'] },
    { key: 'expiry', label: 'Expiry date', type: 'date' },
    { key: 'owner', label: 'Owner', type: 'text' },
    { key: 'note', label: 'Note', type: 'text', long: true },
  ],
}
export const isOverdue = (r) => r.expiry && r.expiry < new Date().toISOString().slice(0, 10)
export const isDone = () => false   // no "done" concept for this tool
// … uid(), emptyRecord(), seed() with 8–12 realistic demo certificates, formatDate()

…runs npm install && npm run build, and delivers dist/index.html — renamed to something like vendor-certificates.html — ready to double-click open.

Example 2 — enough detail up front to skip the questions

If your first message already answers all five questions, the agent skips straight to building — AGENTS.md explicitly tells it to state its assumptions instead of asking when the prompt already has enough in it:

Build me an equipment maintenance log based on openToolbox. One record is a "maintenance ticket" — machine name, technician, service date, status (open/scheduled/done), and a cost in euros. Machine name is the headline, table shows machine, technician, date, status, cost. A ticket is overdue if the service date has passed and it's not done. Turn the AI assistant on so whoever uses this can ask "what's overdue" without digging through the table — but keep write access off, read-only is enough.

Nothing to clarify here — the agent states back its assumptions in one line ("assuming 'cost' is a plain number, no currency formatting beyond the field label") and goes straight to src/domain.js, setting ai.enabled: true and ai.allowWrite: false in the default settings.

Example 3 — when the shape doesn't fit

Not everything is a list-with-filters. If you ask for something openToolbox genuinely isn't built for, a well-briefed agent says so instead of forcing it:

Build me a project-cost calculator based on openToolbox — enter hours and a day rate per role, it totals the budget.

A calculator isn't records-with-fields, so per AGENTS.md, the honest answer is: "That's a calculator, not a list — openToolbox's schema-driven table/form doesn't fit it well. I can either (a) keep the file persistence, encryption and AI plumbing and replace the list view with a calculator layout, or (b) suggest a different starting point. Which do you want?" — rather than awkwardly bending a table-and-filters UI into something it was never meant to be.

Why this works without you reading the source

  • One file to read, one file to write. AGENTS.md is short on purpose and is the only context the agent strictly needs; src/domain.js is the only file it should normally touch.
  • The schema drives everything else. Table columns, the edit form, sidebar filters, CSV export, what the AI assistant is told about your data, and the validation of anything it proposes back — all generated from one SCHEMA object, not hand-wired per tool.
  • The failure modes are already documented, so the agent doesn't rediscover them: don't add a network dependency, don't use browser storage, don't touch the Vite config in ways that silently produce a broken 9 KB file. See Building Your Own Tool for the full list and the reasoning behind each one.
  • It ends with a real deliverable — one dist/index.html, self-contained, that opens by double-click with no server and no install.

Want to go deeper?

Lower priority: developing openToolbox itself

The pages above are about using the repo to build a tool. If instead you want to change the template itself — fix a bug, add a feature to the framework, touch the build pipeline — that's a different, much smaller audience:

License

Apache License 2.0. Dependencies: Preact (MIT), Vite (MIT), Playwright for tests only (Apache 2.0). The built file loads nothing at runtime.

Clone this wiki locally