What to watch out for
These rules decide whether a tool runs reliably on a phone. On top come lessons from building the gallery tools.
The basic rules
Everything in one file
Embed images as SVG in the code or as data links, use no web fonts, and copy libraries into the file instead of linking them. Otherwise the tool stays empty offline.
Phone first
Set <meta name="viewport" content="width=device-width, initial-scale=1">. Tap targets at least 48 px tall, text at least 16 px, no feature that only works with hover (mouse pointer).
Save data on purpose
Put values into localStorage and save after every change. Do not keep anything important only in memory: it is gone as soon as the tool closes.
Easy to read
High contrast, clear labels, no text below 14 px. To fit the toolbox: dark background, light text, one amber accent.
No secrets in the code
A tool file is readable text. Whoever receives it sees everything in it. Do not put passwords, keys or private data in the file before you pass it on.
Do not trust unknown tools blindly
Isolation is protection, not a free pass. Check where a tool comes from and only switch on extended permissions when you really need them.
Test first
Open new code in the editor and look at it in the preview. Try the main paths, including unusual input.
Use versions
Keep the name and the new file becomes the new version. You can bring back the last three versions if a change breaks something.
Lessons from building the gallery
While building the shared kit for the gallery tools we ran into a few pitfalls that affect almost every tool. These solutions apply to your tools just the same.
| Topic | What happens | How to do it right |
|---|---|---|
| Timers in the background | When a tool runs in the background or the screen is off, the phone throttles setInterval. Counted seconds then fall behind. | Remember the start time (Date.now()) and compute the remaining time from it on every tick instead of counting seconds. |
| Sorting by dragging | Drag and drop (HTML5) does not work with touch on Android. | Offer “up” and “down” buttons for each entry. |
| Images in the backup | Images stored as a Blob or object URL do not end up in the toolbox backup. | Shrink images (for example at most 512 px, JPEG) and store them as a data link. |
| Storage full or blocked | localStorage can be full or missing. Without a safeguard the tool stops with an error. | Wrap every access in try/catch, fall back to memory and show a note that nothing is being saved right now. |
| New version, old data | After a rebuild, stored data no longer matches the code. | Store data with a version number ({ v: 2, daten }) and migrate old versions when loading. |
| Numbers and dates | Home-made formats are wrong in other languages (decimal comma, dates, plurals). | Use Intl: NumberFormat, DateTimeFormat, PluralRules and RelativeTimeFormat. It is built into the browser and works offline. |
| Annoying confirmations | Constant “Really delete?” questions get clicked away and then no longer protect anything. | Act right away and offer “Undo” for ten seconds. Only deleting everything asks first. |
| alert and confirm | These windows block the tool and look different on every device. | Build your own dialogs that close with Esc and return the focus. |
| Sound on phones | Sounds only start after a touch. A timer that beeps on its own otherwise stays silent. | Prepare the sound (AudioContext) on the first tap on “Start”. |
| Screen turns off | With timers, sheet music or recipes the display goes dark. | Request a wake lock (navigator.wakeLock) and accept a refusal without an error. |
| Minifying code | Minified code is hard to read for you and for “Change with AI”. | Keep the code readable. A file of around 60 to 90 KB is no problem. |
See also: Gallery blueprint · When something does not work