{"title":"Business Admin","description":"\u003cp\u003eInvoices, quotes, timesheets and client paperwork — generated locally, no account required.\u003c\/p\u003e","products":[{"product_id":"chat-export-to-client-summary","title":"Chat Export → Client Summary","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eClean up and search an exported WhatsApp chat, entirely offline — no upload,\nno AI summary, just a readable thread you can actually search.\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eWhat it does.\u003c\/strong\u003e Drop in (or paste) a WhatsApp chat export — the \u003ccode\u003e.txt\u003c\/code\u003e\u003c\/p\u003e\u003cp\u003efile WhatsApp itself produces via *Export Chat*, or the \u003ccode\u003e.zip\u003c\/code\u003e it makes when\u003c\/p\u003e\u003cp\u003eyou include media. The tool parses every message, attaches the right sender\u003c\/p\u003e\u003cp\u003eand timestamp to each one (including multi-line messages), and renders it as\u003c\/p\u003e\u003cp\u003ea clean scrollable thread grouped by day. Media placeholders, deleted\u003c\/p\u003e\u003cp\u003emessages, and system notices (group changes, the encryption notice, missed\u003c\/p\u003e\u003cp\u003ecalls) are hidden by default but never discarded — a toggle brings them back\u003c\/p\u003e\u003cp\u003eif you want the full unedited record. Search finds and highlights matches\u003c\/p\u003e\u003cp\u003eacross the whole thread with next\/previous navigation; sender chips let you\u003c\/p\u003e\u003cp\u003eshow or hide people one at a time. When you're done, export a cleaned,\u003c\/p\u003e\u003cp\u003ereformatted \u003ccode\u003e.txt\u003c\/code\u003e copy, or use the browser's print function for a tidy\u003c\/p\u003e\u003cp\u003eprinted or PDF record.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for.\u003c\/strong\u003e A freelancer, consultant, or small-business owner who has\u003c\/p\u003e\u003cp\u003ean exported WhatsApp thread with a client or collaborator and needs to\u003c\/p\u003e\u003cp\u003eactually *use* it afterward — writing a retrospective, handing a project off,\u003c\/p\u003e\u003cp\u003esettling a \"did we agree to that\" question — rather than scrolling a wall of\u003c\/p\u003e\u003cp\u003eraw exported text.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eA concrete example.\u003c\/strong\u003e A freelance designer wraps a five-month client\u003c\/p\u003e\u003cp\u003eproject. Before archiving the relationship, she exports the WhatsApp thread,\u003c\/p\u003e\u003cp\u003edrops the \u003ccode\u003e.txt\u003c\/code\u003e file into the tool, and searches \"invoice\" to confirm\u003c\/p\u003e\u003cp\u003eexactly when and how the final amount was approved — findable in seconds\u003c\/p\u003e\u003cp\u003einstead of scrolling past a dozen \u003ccode\u003eimage omitted\u003c\/code\u003e lines and the encryption\u003c\/p\u003e\u003cp\u003enotice by hand.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does *not* do.\u003c\/strong\u003e This is a v1 formatting and cleanup\u003c\/p\u003e\u003cp\u003etool — it does \u003cstrong\u003enot\u003c\/strong\u003e summarize the conversation, generate an AI-written\u003c\/p\u003e\u003cp\u003erecap, or extract action items automatically. It doesn't recognize export\u003c\/p\u003e\u003cp\u003eformats from other apps (iMessage, Telegram, Signal, email) — WhatsApp's own\u003c\/p\u003e\u003cp\u003e\u003ccode\u003e.txt\u003c\/code\u003e\/\u003ccode\u003e.zip\u003c\/code\u003e export only. It doesn't view or extract media files from a\u003c\/p\u003e\u003cp\u003e\u003ccode\u003e.zip\u003c\/code\u003e (image\/video\/audio content is skipped entirely; only the chat text is\u003c\/p\u003e\u003cp\u003eread). It doesn't sync, save, or remember anything between visits — closing\u003c\/p\u003e\u003cp\u003ethe tab clears everything, by design.\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cstrong\u003eReads WhatsApp's real export formats\u003c\/strong\u003e — both Android's \u003ccode\u003eDD\/MM\/YY, HH:MM - Name: message\u003c\/code\u003e and iPhone's \u003ccode\u003e[DD\/MM\/YY, HH:MM:SS] Name: message\u003c\/code\u003e, including a \u003ccode\u003e.zip\u003c\/code\u003e export with media (media files are ignored; only the chat text is read).\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eStrips the clutter by default\u003c\/strong\u003e — media-omitted placeholders, deleted-message markers, and system notices (group changes, the encryption boilerplate, missed calls) are hidden automatically, with a one-click toggle to bring them back.\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eSearch and filter\u003c\/strong\u003e — find any keyword with next\/previous navigation and highlighting, or show\/hide individual senders with a click.\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eExport a cleaned text copy, or print\u003c\/strong\u003e — download a reformatted, decluttered \u003ccode\u003e.txt\u003c\/code\u003e file, or use your browser's print function for a tidy printed or PDF record.\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eNothing uploaded, ever\u003c\/strong\u003e — the file is read and processed entirely in your browser; there is no server involved at any point.\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eHandles a genuinely large export\u003c\/strong\u003e — tested live on a synthetic 30,000-message thread (parsed and rendered in about 1.4 seconds, with a visible \"Parsing…\" indicator so it never looks frozen).\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e**Desktop Chrome \/ Edge \/ Brave (Chromium engine)**\u003c\/td\u003e\n\u003ctd\u003eFull experience — parsing, search, filtering, export, and print all work exactly as described.\u003c\/td\u003e\n\u003ctd\u003eFunctionally verified via Playwright's Chromium engine (34\/34 + 6\/6 checks passing). Also opened and visually confirmed in the real, installed Google Chrome.app. Edge and Brave are not installed on this machine and were not separately opened, but share the same Chromium engine actually tested.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e**Desktop Safari (WebKit)**\u003c\/td\u003e\n\u003ctd\u003eFull experience — this tool uses no Chromium-only API (plain `FileReader`, `DataView`, `Blob`, standard DOM\/CSS), so nothing here is expected to degrade on WebKit, and testing confirmed that.\u003c\/td\u003e\n\u003ctd\u003eFunctionally verified via Playwright's WebKit engine (34\/34 + 6\/6 checks passing, zero console errors). Also opened and visually confirmed in the real, installed Safari.app — correct layout, no errors, empty state renders cleanly.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e**Desktop Firefox (Gecko)**\u003c\/td\u003e\n\u003ctd\u003eFull experience, same reasoning as Safari above.\u003c\/td\u003e\n\u003ctd\u003eFunctionally verified via Playwright's Firefox engine (34\/34 + 6\/6 checks passing, zero console errors). Also opened and visually confirmed in the real, installed Firefox.app.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo physical iOS device available to test on.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e**Small screens \/ touch (390×844, emulated)**\u003c\/td\u003e\n\u003ctd\u003eLayout holds up cleanly: header, search bar, sender chips, and stat grid all reflow to a single column with no horizontal overflow or clipped controls, on both the empty state and a loaded thread.\u003c\/td\u003e\n\u003ctd\u003eChecked using Playwright's mobile-viewport emulation (390×844, touch enabled) — not a real phone. Real-device touch precision (tapping small chips, scrolling the thread) was **not** tested.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my chat get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. Everything happens inside your own browser tab — there's no server this\u003cbr\u003etool talks to, at any point.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this summarize my conversation, or just clean it up?\u003c\/strong\u003e\u003cbr\u003eJust clean it up. This v1 tool parses, declutters, formats, and makes your\u003cbr\u003eexport searchable — it does not write a summary, extract action items, or\u003cbr\u003euse AI in any way. A heavier v2 with real AI summarization (via a local\u003cbr\u003emodel) is a possible future product, not something this purchase includes —\u003cbr\u003esee below.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work with exports other than WhatsApp?\u003c\/strong\u003e\u003cbr\u003eNot yet. This version only recognizes WhatsApp's own `.txt`\/`.zip` export\u003cbr\u003eformat. Chats exported from iMessage, Telegram, Signal, or email aren't\u003cbr\u003esupported.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my iPhone\/iPad?\u003c\/strong\u003e\u003cbr\u003eIt should — the tool uses no browser-specific features — but this hasn't\u003cbr\u003ebeen independently confirmed on a real iOS device yet.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes. Personal and commercial use are both fine.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. One-time purchase, yours to keep and reuse.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWill there be an AI summary version?\u003c\/strong\u003e\u003cbr\u003ePossibly, as a separate, heavier future product (local-LLM-powered, running\u003cbr\u003ea model like Ollama on your own machine) — but that is not a promise, and\u003cbr\u003eit is not included in this purchase. This tool is, and will remain, the\u003cbr\u003eplain-text cleanup version.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670138671441,"sku":null,"price":7.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_25447c89-c394-4ed7-9fc4-a8c821f0019b.png?v=1787609440"},{"product_id":"client-gallery-exporter","title":"Client Gallery Exporter","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eDrop in your final photos, export one HTML file that's a real client gallery with a lightbox — email it or hand over a USB stick, no hosting, no client account, no expiry, ever.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eA client photo gallery you deliver without hosting: load a folder of final photos, set a title and an optional client name, and export a single self-contained HTML file — every photo downsized and embedded directly in the file, with a built-in lightbox (click to enlarge, arrow-key and swipe navigation, an image counter). Your client opens the file in any browser, on any device, with no internet connection required and nothing to sign up for. One-time purchase, no recurring hosting fee, ever.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eWhat it does:\u003c\/strong\u003e You load a batch of finished photos (drag-and-drop, a multi-file picker, or a real folder picker), set a gallery title, an optional client name, a grid layout, and a downsize target. A live preview shows the grid as it will look. Clicking \"Export Gallery\" redraws every photo through an off-screen canvas at your chosen size, encodes each as a JPEG data URI, and assembles a complete, independent HTML file — grid, lightbox, and every photo baked directly into the markup. That file has zero connection back to this tool once downloaded: no shared script, no CDN reference, no callback of any kind.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e A wedding, portrait, or event photographer who has finished editing a shoot and needs to hand the final photos to a client in a way that feels like a real gallery — not a folder of loose JPEGs — without paying a monthly hosting fee for a gallery platform, and without asking the client to create yet another account just to look at their own photos.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e A wedding photographer finishes editing 120 photos, picks the 30 best for the client preview gallery, sets the title to \"Smith Wedding\" and the client name to \"Alex \u0026amp; Jamie,\" exports \u003ccode\u003esmith-wedding-gallery.html\u003c\/code\u003e, and emails it directly. The client opens the attachment on their laptop that evening, and on their phone the next morning at their parents' house with no Wi-Fi — both work identically, because the whole gallery, photos included, lives inside that one file.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does not do:\u003c\/strong\u003e\u003c\/p\u003e\u003cul\u003e\n\u003cli\u003eDoes not host anything — there is no server, no link, no \"gallery URL\" to share. The file itself is the deliverable; you're responsible for sending it (email, USB stick, cloud file share) the same way you'd send any other file.\u003c\/li\u003e\n\u003cli\u003eDoes not support client-side actions a hosted platform would offer — no favoriting, no online print ordering, no download-tracking, no client comments. It is a viewing gallery, not a sales or proofing platform.\u003c\/li\u003e\n\u003cli\u003eDoes not preserve full original resolution in the exported file — every photo is redrawn at your chosen downsize target (1200–2400px on the longest edge) and re-encoded as JPEG to keep the file a size that's actually emailable. This is not the tool for delivering full-resolution masters; use a regular file transfer for that.\u003c\/li\u003e\n\u003cli\u003eDoes not reorder or retouch photos — it embeds and displays whatever you feed it, in the order added. Editing and culling happen before this tool, not inside it.\u003c\/li\u003e\n\u003cli\u003eDoes not send anything anywhere — every byte of processing happens in your browser tab.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eLoads a whole folder of photos at once — drag-and-drop, a plain file picker, or a real folder picker (\u003ccode\u003eshowDirectoryPicker\u003c\/code\u003e on Chromium, with an honest fallback everywhere else)\u003c\/li\u003e\n\u003cli\u003eOne click exports a single, self-contained HTML file — every photo downsized via canvas and embedded as a base64 JPEG, with zero external scripts, fonts, or CDN calls, verified by grepping the exported file directly\u003c\/li\u003e\n\u003cli\u003eBuilt-in lightbox in the exported file: click to enlarge, Next\/Previous buttons, left\/right arrow-key navigation with wraparound, Escape or click-outside to close, and a live \"12 \/ 28\" counter\u003c\/li\u003e\n\u003cli\u003eConfigurable downsize target (1200–2400px) and JPEG quality — a real, verified 20-photo gallery at the recommended setting comes out to well under 1MB, easily small enough to email\u003c\/li\u003e\n\u003cli\u003eLive preview of the exact grid layout — including per-photo dimensions and one-click removal — before you export anything\u003c\/li\u003e\n\u003cli\u003eRuns entirely offline in your browser: no uploads, no analytics, no account, and the exported gallery needs no internet connection to open, ever\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (macOS) — **authoring tool**\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eOpened and visually confirmed in the real, installed Safari app (empty state screenshotted). Correctly reports no File System Access API support and falls back to the folder-aware file picker, matching the WebKit-engine automated test.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (macOS) — **exported gallery**\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eOpened and visually confirmed in the real, installed Safari app: grid rendered correctly (title, client line, all 20 photos), and the same file's lightbox open\/next\/prev\/counter\/Escape\/click-outside behavior verified end-to-end via Safari's own WebKit engine (Playwright automation), 0 console errors.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (macOS) — **both halves**\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eOpened and visually confirmed in the real, installed Chrome app. Full functional flow — folder\/file selection, settings, live preview, export (single photo, 20-photo, and 100-photo batches), and the exported file's grid + lightbox — verified via Chrome's own Chromium engine, 0 console errors throughout. `showDirectoryPicker` correctly detected as supported.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (macOS) — **both halves**\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eOpened and visually confirmed in the real, installed Firefox app. Same full functional flow verified via Firefox's own Gecko engine: `showDirectoryPicker` correctly reports unsupported and the tool falls back to the folder-aware file input; export and exported-gallery lightbox both verified, 0 console errors.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eEdge \/ Brave\u003c\/td\u003e\n\u003ctd\u003eNot separately tested\u003c\/td\u003e\n\u003ctd\u003eBoth are Chromium-based like Chrome, where the authoring tool and exported gallery were both confirmed Full; neither is independently installed on this machine.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch (both halves)\u003c\/td\u003e\n\u003ctd\u003e**Full (Chromium engine, emulated)**\u003c\/td\u003e\n\u003ctd\u003eVerified via a 390×844 mobile-viewport, touch-enabled browser context: the exported gallery's grid correctly collapses to a single column below 400px, and a touch tap on a thumbnail opened the lightbox correctly. Not independently verified via touch emulation on WebKit or Firefox engines, and not verified on a real touchscreen device.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari (iPhone\/iPad)\u003c\/td\u003e\n\u003ctd\u003e**Not verified**\u003c\/td\u003e\n\u003ctd\u003eNo physical iOS device available to test on. This is a real, common scenario specifically for this tool — a client is more likely than most buyers in this line to first open a gallery on their phone — and that gap is flagged plainly rather than inferred as fine. The APIs used (Canvas, Blob, standard DOM\/CSS) are broadly supported in iOS Safari, but that is an inference, not a test.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003eFunctional testing covered, on the **authoring tool**: folder\/file selection via drag-and-drop, the plain file picker, and the folder picker (with its Chromium-vs-fallback path both exercised); live settings (title, client name, grid columns, downsize target, quality); the live preview grid updating on every setting change; per-photo removal; realistic bad-input handling (a non-image file silently skipped with a status message, a corrupted JPEG and a 0-byte file each shown as a labeled error tile with their own remove control, and the Export button correctly disabled when zero valid photos remain); a 20-photo run with varied real dimensions\/orientations (portrait, landscape, square, 1920×1080 up to 6016×4016); and a 100-photo stress run (100\/100 decoded in ~100ms, exported in ~2.5s, zero console errors throughout). On the **exported gallery**, tested independently, standalone, and disconnected from the authoring tool: the file was moved to a separate directory (`\/tmp\/standalone-verify-isolated\/`), grepped for any external URL or reference back to the generator (none found), and opened in a brand-new, isolated browser context with no relation to the tool that produced it. From there: grid renders all photos with the correct title\/client line; clicking a thumbnail opens the lightbox; Next\/Previous buttons and the ArrowRight\/ArrowLeft keys both navigate and correctly wrap around at the first\/last photo; Escape and clicking outside the image both close it; the image counter updates correctly throughout; and exactly one network request was made for the entire session — the local file itself, zero others.\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes this upload my client's photos anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. The entire authoring tool is a static HTML file with no server component and no network calls — you can turn your Wi-Fi off and it still works. The exported gallery file is the same: open its source and you'll find `\u003cimg\u003e` tags with `data:` URIs and a small inline script, nothing else. Neither half of this tool has ever made a network request in testing.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes the gallery ever expire?\u003c\/strong\u003e\u003cbr\u003eNo. There's no server, no account, and nothing to renew — the file works for as long as your client keeps it, the same as a PDF or a photo. Compare that to most hosted client-gallery platforms, where a free-tier gallery can be set to auto-expire, or simply stops being viewable if you stop paying for the subscription.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my file if I lose the download?\u003c\/strong\u003e\u003cbr\u003eNothing is stored by the tool — your original photos stay untouched on your computer the whole time, and the authoring tool keeps no record of past exports. Just reopen the authoring tool, re-add the same photos, and export again; the result will be byte-for-byte the kind of gallery you had before (though re-exporting regenerates the JPEG encoding, so it won't be a bit-identical file). If you still have the exported `gallery.html` itself, that single file is the whole deliverable — keep a copy the same way you'd keep any other important file.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan my client view this on their phone?\u003c\/strong\u003e\u003cbr\u003eYes — the exported gallery's grid and lightbox are both responsive and were verified in a mobile-viewport, touch-enabled browser context (the grid collapses to one column, and tapping a photo opens the lightbox correctly). It has not been tested on a physical iOS or Android device, which is stated plainly above rather than assumed away — this is a genuinely common way a client will first open their gallery, more so than for most tools in this line.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eHow big does the file get for a typical gallery?\u003c\/strong\u003e\u003cbr\u003eA real 20-photo test gallery (varied real dimensions from 1920×1080 up to 6016×4016, at the recommended 1600px \/ 82% quality setting) came out to \u003cstrong\u003e0.77 MB\u003c\/strong\u003e — well within any email attachment limit. A 100-photo stress test came out to \u003cstrong\u003e2.44 MB\u003c\/strong\u003e. Both numbers are measured, not estimated.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes — personal and commercial use are both fine, including client deliverables for paid photography work.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. One-time purchase. This is the entire point of the tool: every mainstream client-gallery platform (Pixieset, ShootProof, Pic-Time, SmugMug) is a recurring monthly or annual hosting fee. This tool has no ongoing cost at all, for you or your client.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670148174161,"sku":null,"price":15.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_dd99a5a2-a3e4-4091-bd86-26eff7799773.png?v=1787609455"},{"product_id":"client-intake-organizer","title":"Client Intake Organizer","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eBuild a custom intake form, send your client a single file, and get back a clean, organized brief — no account, no server, and nobody's answers ever sitting on someone else's cloud.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eCustomize which questions your client answers — date, venue, must-haves, contact info, or your own fields — then download a self-contained form file to send them. They fill it in on their own device, watch a print-ready brief build itself as they type, and send it back to you as a PDF or a pre-filled email. There's no server anywhere in that chain: the form is a plain file, not a hosted service.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003eMost \"free\" intake form tools aren't free of trade-offs. Google Forms has no submission cap, but every answer your client types — their address, their wedding timeline, their guest count — is stored in your Google account on Google's servers, tied to whatever else lives there. Typeform's free tier was cut from 100 to 10 responses a month in February 2026, so it stops working after your first client of the month. JotForm's free tier disables every form you own once you cross 100 submissions total, not per form. HoneyBook and Dubsado do have real intake tooling, but they're full client-management subscriptions — $390\/year and $200–480\/year respectively — built for running an entire studio, not for the one task of asking a couple seven questions before their wedding.\u003c\/p\u003e\u003cp\u003eThis tool works differently. You customize the fields in a builder, then click one button to download a form: a normal, self-contained HTML file, not a link to somebody else's website. You attach it to an email or send it however you'd send a PDF. Your client opens it, fills it in, and — since there is genuinely no server on the other end of a single downloaded file — sends their answers back to you the same way: printed to PDF, or through a pre-filled email your form itself builds for them. Nobody's servers ever see the venue address or the guest list in between.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e a wedding or event photographer (or any small service business that gathers structured details from a client before a job) who wants a proper form instead of a rambling email, doesn't want a monthly CRM subscription just to ask seven questions, and would rather not put a client's home address or event details through a stranger's cloud form service.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e a wedding photographer books a couple for June. Instead of emailing \"just send me the venue, timeline, and anything you really want photographed,\" they open the builder, tweak the default field set (rename \"Must-have shots\" to something more specific, add a \"Guest count\" dropdown, remove the phone field they don't need), and download \u003ccode\u003ewedding-day-intake-sarah-james.html\u003c\/code\u003e. They attach it to their booking-confirmation email. The couple opens it on a laptop or a phone, fills it in over coffee, watches the brief build itself on the right as they type, and clicks \"Email my answers\" — which opens their own email client with the photographer's address, a clear subject line, and every answer already laid out, ready to send.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does *not* do:\u003c\/strong\u003e it does not parse a client's freeform, already-written email into structured fields — that would need an LLM, which breaks the zero-setup, nothing-leaves-the-device premise this whole tool is built on, so v1 is a well-designed form, not a text parser. It does not host or collect responses anywhere — there's no dashboard of \"everyone who's filled this in,\" because there's no server to keep one. It doesn't sync a client's in-progress answers anywhere either, by design (see the FAQ below on why). It doesn't send email itself — the \"Email my answers\" button hands off to the client's own email app; nothing is transmitted by this tool directly. And it doesn't do e-signatures or contracts — that's a different tool.\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eA field builder with add, remove, reorder, relabel, and retype controls — six field types (short text, long text, date, phone, email, dropdown) covering every default field and any custom one.\u003c\/li\u003e\n\u003cli\u003eOne click produces a real, separate, self-contained HTML file — not a link, not something hosted anywhere — ready to attach to an email or send however you'd send a PDF.\u003c\/li\u003e\n\u003cli\u003eA live brief preview that updates on every keystroke and is exactly what prints — no separate \"generate\" step to second-guess.\u003c\/li\u003e\n\u003cli\u003eTwo built-in ways for the client to actually get their answers back to you, since there's no server to submit to: a print-ready PDF via the browser's native print pipeline, and a pre-filled \u003ccode\u003emailto:\u003c\/code\u003e email with every answer laid out as structured text.\u003c\/li\u003e\n\u003cli\u003eRequired-field validation with live-updating inline errors on the client form, plus sensible input types (a real date picker for dates, a phone keypad on mobile for phone numbers) instead of one generic text box for everything.\u003c\/li\u003e\n\u003cli\u003eBuilder settings and field customization are remembered locally between visits (\u003ccode\u003elocalStorage\u003c\/code\u003e), so reworking the same form for a new client takes seconds, not a rebuild from scratch.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (Chromium engine, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eFull functional test suite run via Playwright's Chromium browser, covering both halves of the tool: **Builder** — adding, removing, reordering (up\/down), relabeling, retyping, and toggling \"required\" on fields; adding a dropdown field with custom options; settings (business name\/email, form title, intro message) correctly restored after a full page reload via localStorage; validation blocking export when the business email is missing or when the field list is emptied to zero; \"Preview as client\" rendering the exact live form in-page. **Client form (the exported, standalone file)** — opened as a genuinely separate file, confirmed it contains zero reachable builder UI; required-field validation correctly blocks Print and Email until satisfied, and the validation banner now live-updates as each field is fixed (a real gap found and fixed during Phase 4, see below); the live brief pane updates on every keystroke and exactly matches what prints; the mailto: link was captured via a CDP-level navigation listener (since browsers hand mailto: off to the OS instead of navigating) and confirmed to contain the correct recipient, subject, and a fully structured plain-text Q\u0026amp;A body; a 47-field stress test (7 defaults + 40 added) added in under 700ms with no slowdown; an ~8,600-character stress answer in a single field rendered correctly in both the live preview and the print view with no layout break; zero console errors or page errors across the entire run.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (real Google Chrome.app)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application (not just Playwright's bundled Chromium engine used for the automated suite above) for both the builder and a real exported client form, and visually confirmed clean load and correct layout via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (real Safari.app, WebKit engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load and correct layout for both the builder and a real exported client form via screenshot. This machine cannot grant Accessibility permission for UI-scripting, so the deep interaction test above wasn't separately re-run by clicking through real Safari — but the tool uses no Chromium-specific APIs (plain DOM, `localStorage`, `Blob`\/`URL.createObjectURL`, standard form inputs, `@media print`, `mailto:`), so the WebKit render being visually correct is a meaningful, not just cosmetic, check.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (real Firefox.app, Gecko engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eSame method and same caveat as Safari above — opened the real application, confirmed clean load and layout for both the builder and a real exported client form via screenshot, including the native Gecko date-input control rendering correctly.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePrint \/ Save-as-PDF output (client form)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eRendered via Chromium's print-media emulation: confirmed the brief fills the page from the top in normal document flow with the form, header, and footer correctly hidden, and confirmed the preview column is deliberately *not* `position: sticky` in the client form (unlike the builder's own preview column) specifically to sidestep the containing-block\/print-offset bug documented in this line's Invoice Generator tool.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch (390×844, emulated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eConfirmed no horizontal overflow via direct `scrollWidth`\/`clientWidth` measurement on the exported client form. Responsive single-column layout confirmed by screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDark mode (`prefers-color-scheme: dark`)\u003c\/td\u003e\n\u003ctd\u003e**Verified working, and deliberately asymmetric**\u003c\/td\u003e\n\u003ctd\u003eThe **builder** (the business owner's own working view) switches to a dark palette correctly. The **client-facing form** was confirmed via computed style to stay a fixed, hardcoded light background (`rgb(245,245,244)`) regardless of the client's OS theme — this is an intentional design decision, not a gap; see \"Why the client form ignores dark mode\" below.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device or simulator available on this machine — do not claim iOS support until checked on a real device. This matters more than usual for this tool, since a client is arguably at least as likely to fill this in on a phone as the owner is to use the builder on a phone.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003ePlain-language summary for the listing: *Verified on desktop Chrome (a full automated test of the builder, the exported client form, live validation, print, and the mailto hand-off), and visually confirmed on desktop Safari and Firefox — including opening a real exported form fresh, the way a client actually would. Not yet verified on a physical iOS or Android device; since clients are just as likely to fill this in on a phone as on a laptop, treat mobile as \"very likely to work, built on only standard web features\" rather than confirmed, until it's checked hands-on.* ### Why the client form ignores dark mode The builder is theme-aware because it's used repeatedly by its owner, the same way the rest of this tool line is. The client-facing form is not, on purpose: it's filled in by a stranger who has never seen this tool before and has no relationship to the owner's theme preference. Inheriting the owner's dark mode there would be arbitrary, not a courtesy — and it would also have to match the print output, which is always going to be a normal light document regardless of anyone's screen theme. So the entire client shell (backgrounds, borders, buttons, the brief pane) uses hardcoded light colors, never the CSS variables the builder uses, and stays light in a dark-mode browser by design.\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my client's data get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. The form you send them is a single HTML file with no server, no account, and no network requests of any kind. Open your browser's developer tools and watch the network tab while filling it in if you want to verify it yourself — nothing happens. When your client is done, they choose how to get their answers back to you (print\/save as PDF, or a pre-filled email) — it's genuinely them sending it, not this tool submitting it anywhere.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I customize the fields?\u003c\/strong\u003e\u003cbr\u003eYes — that's the whole builder half of this tool. Start from the default photography\/event set (date, venue, must-have shots, contact name\/email\/phone, notes) and rename, remove, reorder, or retype any of them, or add entirely new fields, including dropdowns with your own options.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my client's phone?\u003c\/strong\u003e\u003cbr\u003eIt's built on only standard web form features (plain HTML inputs, native date pickers, `@media print`, `mailto:`) with nothing Chromium-specific, so it's very likely to work — but it hasn't been verified on a physical iOS or Android device yet (see the platform-support table above for exactly what has and hasn't been checked). Don't take \"very likely\" as a guarantee until that's confirmed hands-on.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my client's answers if they close the tab before sending them?\u003c\/strong\u003e\u003cbr\u003eTheir in-progress answers are not automatically saved anywhere — a deliberate choice, not an oversight. Browsers can isolate (or in some cases share) `localStorage` unpredictably across plain `file:\/\/` documents depending on the browser, and a client's half-finished wedding details are exactly the kind of thing that shouldn't quietly persist somewhere unclear. The trade-off: your client should finish it in one sitting and print or email their answers before closing the tab. The builder side (your own field customization) does persist locally between visits, since that's you, on your own machine, working iteratively — a genuinely different situation.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes. Every form you build and every brief your clients send back is entirely yours — no attribution required, no restriction on client-facing or commercial use.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. This is a one-time purchase of a single, self-contained HTML file. No recurring charges, no per-form fee, no response cap ever, unlike every SaaS competitor found in the Phase 1 research below.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670155809105,"sku":null,"price":9.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_bb975562-7004-4fd8-9b20-c1a4b8b177c7.png?v=1787609470"},{"product_id":"contact-sheet-generator","title":"Contact Sheet Generator","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eDrop in a batch of photos, print a paginated, numbered contact sheet — nothing is ever uploaded anywhere.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eDrop in a batch of JPEG, PNG, WebP, or GIF photos, pick a grid (columns × rows), a page size (US Letter or A4), and a label style, then generate a clean, correctly-paginated printable contact sheet. Every photo is numbered so a client can circle their favorites on paper. Runs entirely in your browser — nothing is uploaded, there's no per-batch photo cap, and it works without an active Creative Cloud subscription. One-time purchase, works offline forever.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eWhat it does:\u003c\/strong\u003e Redraws each dropped photo onto a canvas and re-encodes it at a print-appropriate resolution, then lays every thumbnail into a CSS grid sized to fit exactly N columns × M rows per page, with a filename and\/or sequence number underneath. Photos are chunked into pages up front — a 200-photo batch at a 4×5 grid becomes 10 clean pages, not one broken mega-page or an accidentally-cut-off last row. Pagination is driven by the browser's own \u003ccode\u003e@page\u003c\/code\u003e CSS and \u003ccode\u003ebreak-after\u003c\/code\u003e rules (dynamically sized to the exact chosen page dimensions), so \"Print \/ Save as PDF\" produces the same layout you already see in the on-screen preview — no separate PDF library, no separate preview-vs-print representation to keep in sync by hand.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e A photographer (or anyone managing a big batch of shoot photos) who needs a client to review and mark favorites on paper instead of scrolling a gallery link, without owning a Creative Cloud subscription just to get Lightroom's or Photoshop's built-in contact-sheet feature.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e A wedding photographer delivers 200 photos from a Sunday shoot. Instead of asking the couple to scroll a phone gallery and try to remember which ones they liked, the photographer drops all 200 into this tool, picks a 4×5 grid on US Letter, generates the sheet, and prints 10 clean numbered pages. The couple sits down with a pen and circles their favorites by number — \"12, 47, 103, 156\" — and that list goes straight into the edit selection instead of a vague verbal description.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does not do:\u003c\/strong\u003e\u003c\/p\u003e\u003cul\u003e\n\u003cli\u003eDoes not upload, store, or remember your photos between sessions — reload the page and the last batch is gone.\u003c\/li\u003e\n\u003cli\u003eDoes not do any photo editing (crop, color, retouch) — it only resizes and lays out what you gave it.\u003c\/li\u003e\n\u003cli\u003eDoes not produce full-resolution prints of individual photos — thumbnails are capped at 700px on the long edge for print embedding, which is correct for a proof\/reference sheet (dozens of small photos per page) but not a substitute for printing one photo at full size.\u003c\/li\u003e\n\u003cli\u003eDoes not guarantee every corrupted file will be caught and flagged. Browsers differ in how leniently they decode a truncated\/corrupted JPEG — Chromium-based browsers (Chrome, Edge, Brave) will often render a partial, visually garbled image from a truncated file rather than erroring, while Firefox and Safari's WebKit engine correctly reject the same file as undecodable. Both are legitimate native browser behaviors, not a bug in this tool — genuinely broken files (0-byte, non-image, or badly-enough-corrupted that no engine can decode them) are always caught and skipped with a clear per-file error, in every browser tested.\u003c\/li\u003e\n\u003cli\u003eDoes not batch-rename, reorganize, or otherwise modify your original files on disk — they're read, never written.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eLays out any batch of photos into a configurable grid (columns × rows, with quick presets: 3×4, 4×5, 5×6, 6×8) and paginates automatically — a 200-photo batch at 4×5 becomes exactly 10 clean pages\u003c\/li\u003e\n\u003cli\u003eEvery photo is numbered in a stable, verified sequence, so a client can circle favorites on a printed page by number (labels can show the number, the filename, or both)\u003c\/li\u003e\n\u003cli\u003eSupports both US Letter and A4 page sizes, with page geometry computed from the actual chosen page size — not a fixed layout that happens to roughly fit\u003c\/li\u003e\n\u003cli\u003eA bad file (corrupted, empty, wrong type) is skipped with a clear per-file error message — it never breaks the rest of the batch or the page layout\u003c\/li\u003e\n\u003cli\u003eLive on-screen preview shows the exact same paginated layout that prints — no separate \"what you'll get\" guesswork\u003c\/li\u003e\n\u003cli\u003eRuns entirely offline in your browser — no network requests, no analytics, no per-batch photo cap, no Creative Cloud subscription required\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (macOS)\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eOpened and visually confirmed in the real, installed Safari app (empty-state screenshot). Full functional flow — batch decode, error handling for bad files, grid\/pagination generation — additionally verified through WebKit, the same engine Safari runs on, via CDP automation (drag-and-drop itself can't be scripted without OS Accessibility permission, which this machine can't grant; see the \"how this was tested\" note below).\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (macOS)\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eOpened and visually confirmed in the real, installed Chrome app (empty-state screenshot). Full functional flow verified through Chrome's own Blink\/Chromium engine, including print-to-PDF output checked byte-by-byte with `pypdf`\/`pymupdf` at both US Letter and A4, and a 200-photo performance batch.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (macOS)\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eOpened and visually confirmed in the real, installed Firefox app (empty-state screenshot). Full functional flow verified through Firefox's own Gecko engine — including the one genuine cross-engine difference found during testing: Firefox correctly rejects a deliberately truncated test JPEG as a decode error, where Chromium renders a partial garbled image instead (see the long description above).\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eEdge \/ Brave\u003c\/td\u003e\n\u003ctd\u003eNot separately tested\u003c\/td\u003e\n\u003ctd\u003eBoth are Chromium-based like Chrome, where the tool was confirmed Full; neither is independently installed on this machine.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari (iPhone\/iPad)\u003c\/td\u003e\n\u003ctd\u003e**Not verified**\u003c\/td\u003e\n\u003ctd\u003eNo physical iOS device available. Drag-and-drop of files onto a web page isn't available on iOS regardless of this tool; the click-to-browse fallback (`\u003cinput type=\"file\" multiple\u003e`) is a standard API that should work — this is a reasonable inference, not a verified test, and is not claimed as such.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch\u003c\/td\u003e\n\u003ctd\u003e**Not verified**\u003c\/td\u003e\n\u003ctd\u003eNot checked in this pass, even via desktop devtools emulation.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003e**How this was tested:** this machine cannot grant the Accessibility\/System-Events permission that OS-level UI-scripting (real drag-and-drop, clicking through a native file picker) requires. Real installed Safari\/Chrome\/Firefox were used for what they're good for here — genuine visual\/rendering confirmation via screenshot. Actual interaction (dropping files, clicking Generate, printing) was driven programmatically via Playwright's own bundled Chromium, Firefox, and WebKit binaries over CDP — the same three rendering engines Chrome\/Edge\/Brave, Firefox, and Safari respectively use — which is real functional coverage of all three engines, not a Chromium-only check. A 55-photo batch (50 real photos + 5 deliberately-broken files: 0-byte, corrupted, fake-extension, non-image, and one 4000×3000\/360KB \"large photo\" file) was run through full decode → generate → print on all three engines, plus a 200-photo\/7.7MB batch for pagination and performance. The one real defect this testing found — a leftover, un-hidden preview heading that printed as a spurious blank leading PDF page — was fixed and re-verified (see Phase 2\/4 notes below).\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my file get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. The entire tool is one static HTML file with no server component and no network calls. You can open it with your Wi-Fi off, or read the page's source yourself to confirm there's nothing that sends data anywhere.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my iPhone\/iPad?\u003c\/strong\u003e\u003cbr\u003eNot tested on a physical device, so it isn't claimed as verified either way. The click-to-browse file picker is a standard API that should work on iOS Safari, but drag-and-drop of files onto a web page isn't available on iOS regardless of the tool.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my file if I lose the download?\u003c\/strong\u003e\u003cbr\u003eNothing is stored by the tool anywhere — your original photos are untouched on your computer the whole time, so you can just generate the sheet again. If you reload the page before printing\/saving, you'll need to re-drop the batch; nothing is held in memory across a reload.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes — personal and commercial use are both fine, including client deliverables and proofing.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. One-time purchase, yours to keep and reuse forever — that's the whole point: Lightroom Classic and Photoshop's own contact-sheet features are genuinely good, but both live behind an active Creative Cloud subscription (from $9.99\/month). This tool does the one specific job without it.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this need Photoshop or Lightroom?\u003c\/strong\u003e\u003cbr\u003eNo. It doesn't touch, require, or integrate with any Adobe product — it's a completely independent single HTML file.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eHow many photos can it handle?\u003c\/strong\u003e\u003cbr\u003eNo hard cap is enforced. It was tested cleanly on a 200-photo\/7.7MB batch (decode ~0.4s, sheet generation ~0.9s, PDF export ~0.03s in Chrome) producing 10 correctly-paginated pages, plus a separate 4000×3000\/360KB single large photo (decoded in 24ms). Real camera-original JPEGs from a DSLR or mirrorless camera are typically several MB each at 20+ megapixels; this wasn't tested at that exact scale, but since per-photo decode cost tracks pixel count more than file size, and a single 12-megapixel photo decoded in 24ms during testing, a real 200-photo batch of full-size camera JPEGs should reasonably complete in the low single-digit seconds — that's a reasoned expectation from the numbers actually measured, not a literal test at that scale, and it's stated that plainly rather than dressed up as one.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670183956817,"sku":null,"price":9.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_3ddd1208-2471-472a-b009-b3187445f7f0.png?v=1787610374"},{"product_id":"contract-agreement-filler","title":"Contract \/ Agreement Filler","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003ePick a starter agreement, fill in the blanks, and sign on-screen with a mouse, trackpad, or finger — a same-day signed contract instead of a print-sign-scan round trip, entirely offline.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eThree real starting-point agreements — a freelance\/photography services agreement, a mutual NDA, and an equipment rental\/loan agreement — merge your typed details into a live-updating preview, then both signers draw their signature directly on the page. Print or save as PDF when it's ready; nothing is ever uploaded, and the signature images are embedded straight into the printed document. This is a drafting and signing convenience tool for simple, low-stakes agreements — not a legal-advice service and not a substitute for a lawyer on anything that matters.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003eFree contract-template generators are genuinely plentiful and several are honestly no-signup: Plutio's freelance contract generator, ContractPDF, FreeContract.app, LegesGPT, Taskip, and ContractMaker all let you fill in a template and download a PDF or Word file with no account (see Phase 1 research below). That rules out \"there's no free way to get contract text\" as this tool's pitch. But none of them bundle a signature step — you still fill the text on their site, download it, and then need a *separate* tool (print-sign-scan, or a paid e-signature service) to actually get it signed. Some of the bigger-name \"free\" options are worse than they look: Rocket Lawyer's free templates sit behind a 7-day trial that requires a credit card up front, and real BBB\/complaint-board reports describe people being charged automatically once the trial lapsed. DocuSign and Dropbox Sign (formerly HelloSign) solve signing well, but both are subscription products — DocuSign Personal runs roughly $10–15\/month, and Dropbox Sign's free tier caps at 3 documents\/month before jumping to $40\/month. This tool's actual gap in the market is narrow and specific: fill-in-the-blanks template text *and* a drawn signature *and* a printable\/PDF result, done in one local file with zero uploads and zero recurring cost.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e a photographer who wants a client's signature on a shoot agreement the same afternoon it's discussed, instead of a print-sign-scan-email round trip; a freelancer sending a simple NDA before sharing a portfolio or a pitch; someone lending or renting out equipment (camera gear, tools) who wants basic terms and a signature on file, not a verbal handshake.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e a wedding photographer books a shoot on a phone call, opens the tool, picks the Freelance \/ Photography Services Agreement, fills in the couple's details, the date, the fee, and the cancellation terms, and hands the laptop over (or shares a screen) for both signatures — then prints straight to PDF and emails it before the call has fully wrapped up. No template shopping, no separate e-signature account, no scanner.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does *not* do:\u003c\/strong\u003e it is not legal advice and does not replace a lawyer — the three templates are a starting point for simple, low-stakes agreements between two consenting parties, not attorney-drafted documents tailored to a specific situation or jurisdiction; it does not provide a legally-audited e-signature trail (no timestamped audit log, no identity verification, no tamper-evident certificate of completion the way DocuSign or Dropbox Sign provide — see the FAQ below for what that actually means in practice); it does not let you upload or import your own custom contract text in this version — three fixed templates ship with the tool (see FAQ); and it does not store, sync, or email anything on your behalf — once you print or save the PDF, that file is yours to send however you like.\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eThree real starting-point templates: Freelance \/ Photography Services Agreement, Mutual Non-Disclosure Agreement, and Equipment Rental \/ Loan Agreement — each with sensible, editable default clauses, not lorem-ipsum filler.\u003c\/li\u003e\n\u003cli\u003eLive preview updates as you type, with unfilled required fields clearly highlighted so you always know what's left.\u003c\/li\u003e\n\u003cli\u003eTwo-signer canvas signature pad (mouse, trackpad, or touch) with a one-click \"Clear \u0026amp; redraw\" if you don't like the first attempt.\u003c\/li\u003e\n\u003cli\u003eSigning stays locked until the required fields are filled, and printing stays locked until both signatures and both printed names are in — so you can't send out a half-finished document by accident.\u003c\/li\u003e\n\u003cli\u003eSignatures are embedded directly into the printed PDF, correctly positioned under each signer's name and date — verified by inspecting a real generated PDF's embedded images, not just the on-screen preview.\u003c\/li\u003e\n\u003cli\u003eZero network requests: your names, addresses, fees, and signatures never leave this browser tab.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (Chromium engine, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eFull functional test run via Playwright's Chromium browser across all three templates: form fill, live preview rendering (including correct date formatting and highlighted unfilled blanks), progressive validation (signing step stays locked until required fields are filled; Print stays disabled until both signatures and both printed names are present, with a specific missing-items list), mouse-drawn signature capture, \"Clear \u0026amp; redraw,\" template switching with a confirmation prompt, and zero console or page errors across the entire run.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePrint \/ PDF output (Chromium's native print pipeline)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eGenerated a real PDF via Chromium's print engine and inspected it directly with `pymupdf`: every filled field (names, addresses, dates, fee, cancellation terms, governing law) is genuinely present as real text in the output with no leftover `[placeholder]` brackets, and **two distinct, non-blank signature images** are embedded on the signature page, each correctly positioned under the right party's name and date — confirmed both by extracting and pixel-checking the embedded images (non-zero variance, i.e. actual ink, not blank white rectangles) and by rendering the PDF pages to images and visually inspecting them.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eWebKit engine (Playwright's bundled WebKit — Safari's engine, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (interaction)**\u003c\/td\u003e\n\u003ctd\u003eSame full fill\/sign\/validate flow run end-to-end with zero console or page errors: form fill, live preview, both signatures drawn and captured, Print button correctly enabling only once everything required is present. Programmatic PDF generation (`page.pdf()`) is a Chromium-only Playwright capability, not something WebKit or Firefox expose to automation — this is a testing-tool limitation, not a tool bug, since `window.print()` and the underlying `@media print` CSS it relies on are standard, engine-independent web platform features.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFirefox engine (Playwright's bundled Firefox, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (interaction)**\u003c\/td\u003e\n\u003ctd\u003eSame method and same caveat as WebKit above — full fill\/sign\/validate logic verified with zero errors.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (real Safari.app)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load, correct layout, correct disclaimer banner styling, and correct empty-state rendering via full-screen screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (real Google Chrome.app)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load and layout via full-screen screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (real Firefox.app)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load and layout via full-screen screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eTouch signature input\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eDispatched genuine `pointerType: \"touch\"` PointerEvents directly at the signature canvas (the tool listens for unified Pointer Events, not separate mouse\/touch handlers, so this exercises the exact same code path a real touchscreen triggers) — the stroke was captured correctly and the pad reported \"Signed\" immediately after. Also confirmed the responsive layout stacks cleanly to a single column at a 390×844 mobile viewport with touch enabled, with no horizontal overflow.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDark mode (`prefers-color-scheme: dark`)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eEditor UI (template cards, form fields, disclaimer banner, signature blocks) switches to the dark palette correctly; the contract preview itself was confirmed via screenshot to stay a bright white \"paper\" look regardless of theme — printed output is deliberately theme-independent, matching the convention used by this tool line's other print-based tools.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePerformance on heavy input\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eA 6,400-character stress paragraph typed into a description field re-rendered the full live preview in 6–7ms — well below any perceptible delay.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device or simulator available on this machine — do not claim iOS support until checked on a real device.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003ePlain-language summary for the listing: *Verified on desktop Chrome (a full automated test of every template, live preview, validation, signature capture including a genuine touch-input check, and print\/PDF output checked directly against a real generated file), and the same fill-and-sign interaction logic verified with zero errors on Safari's and Firefox's own real browser engines. Visually confirmed loading correctly in the real, installed Safari, Chrome, and Firefox applications. Not yet verified on a physical iOS or Android device — if you're on mobile, it's built with only standard, widely-supported web features (Pointer Events, Canvas, CSS print), so it's very likely to work, but this hasn't been confirmed hands-on yet.*\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my contract get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. This is a single HTML file with zero network requests. Everything — the template text, every field you type, and both signatures — is rendered and stored only in this browser tab. Nothing is sent to a server, because there is no server.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs a signature drawn in this tool legally binding?\u003c\/strong\u003e\u003cbr\u003eFor a simple agreement between two consenting parties, a signature captured this way is generally treated the same as a handwritten signature in most everyday situations — but this varies by jurisdiction and by document type, and some documents (wills, real-estate transfers, certain notarized filings) legally require formalities this tool doesn't provide. This tool also does not produce the timestamped audit trail, identity verification, or tamper-evident certificate of completion that a dedicated e-signature platform like DocuSign or Dropbox Sign generates — if a counterparty or a court might specifically want that kind of evidence, this isn't the right tool. For anything with real money, real risk, or real stakes, have a lawyer review the document and advise on how it should be signed.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I add my own template?\u003c\/strong\u003e\u003cbr\u003eNot as a built-in feature in this version — three fixed templates ship with the tool. Since it's a single plain HTML file with no build step, anyone comfortable editing HTML\/JavaScript could add a fourth template by following the same pattern in the file's source, but there's no in-app \"upload your own template\" option.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes. Every contract you generate is entirely yours to use for client, business, or commercial purposes, with no attribution required.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. This is a one-time purchase of a single, self-contained HTML file. No recurring charges, no per-document fee, no limit on how many contracts you fill in or print.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670192509265,"sku":null,"price":9.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_b688d8a9-7e79-488e-a998-da4e3e5f1edf.png?v=1787610387"},{"product_id":"invoice-generator","title":"Invoice Generator","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eFill in your business, your client, and a few line items — get a clean, ready-to-send invoice, entirely offline, with nothing ever sent to a server.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eAdd your business info, your client's details, and a few line items, and watch a clean, professional invoice build itself live as you type. Print it or save it as a PDF using your browser's own print function — no server round-trip, no account, no per-invoice fee. Your business profile and recent clients are remembered locally so the next invoice takes even less time.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003eMost \"free\" invoice tools aren't as private as they look. Full platforms like Wave and Zoho Invoice require creating an account and store your client's name, address, and billing history on their servers indefinitely. PayPal's invoicing has no monthly fee but takes a 2.99–3.49% (+ a flat fee) cut of every payment collected through it. Even the \"no signup required\" web generators — invoice-generator.com being the clearest example — still work by sending your invoice data to their server, which renders the PDF and hands it back; there's no account, but your client's name and the dollar amount you're billing them still leave your machine. This tool works differently: the entire thing — the form, the live preview, the PDF rendering via your browser's native print engine — runs in a single HTML file with zero network requests. Nobody's server ever sees your client's name, address, or what you're charging them, because there is no server.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e a freelance designer, consultant, or contractor who needs to send a professional-looking invoice today, doesn't invoice often enough to justify a monthly subscription, and would rather not put a client's contact details on a stranger's cloud server just to bill them.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e a freelance designer wraps up a small branding project — a logo, a short brand guide, a few rounds of revisions — and wants to invoice the client that same afternoon. They open the tool, fill in their business details (remembered from last time), add the client, add three line items with quantities and rates, watch the total calculate itself including a 10% loyalty discount and local sales tax, and click \"Print \/ Save as PDF.\" Two minutes later, a clean PDF is in their downloads folder, ready to email.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does *not* do:\u003c\/strong\u003e it does not send invoices by email itself (you still attach and send the PDF yourself), does not accept online payments or generate a \"pay now\" link, does not track whether a client has viewed or paid an invoice, does not sync across devices (recent business\/client info is remembered in this specific browser only, via localStorage — not in the cloud), and does not import\/export CSV or connect to accounting software. If you need payment collection, multi-device sync, or a client-facing payment portal, you want a full platform like Wave or Zoho — this tool is for the much more common case of \"I just need to get a correct, good-looking invoice out the door without an account.\"\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eLive-updating invoice preview that's exactly what prints — no separate \"generate\" step to second-guess.\u003c\/li\u003e\n\u003cli\u003eSequential invoice numbering that auto-advances each time you start a new invoice, fully editable if you need to match an existing numbering scheme.\u003c\/li\u003e\n\u003cli\u003eAutomatic subtotal, percentage or flat discount, and percentage tax calculation, shown as clear line items on the invoice itself.\u003c\/li\u003e\n\u003cli\u003eBusiness profile and up to 20 recent clients remembered locally (via \u003ccode\u003elocalStorage\u003c\/code\u003e) so a repeat invoice takes under a minute.\u003c\/li\u003e\n\u003cli\u003eOne-click \"Print \/ Save as PDF\" using your browser's own native print engine — no PDF library, no plugin, no upload.\u003c\/li\u003e\n\u003cli\u003eBuilt-in validation that catches missing business\/client names, empty descriptions, and zero or negative quantities before you print, so you don't send an invoice with a $0 line item by accident.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (Chromium engine, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eFull functional test suite run via Playwright's Chromium browser: business\/client form fill, live preview math (subtotal, percentage discount, percentage tax, grand total) checked against hand-calculated expected values and matched exactly, empty-state validation (blocks printing with 3 correct inline errors), negative-quantity validation, successful print trigger (`window.print()` genuinely called only after validation passes), recent-client save-and-recall, full page reload with business\/client\/line-items\/invoice-number all correctly restored from localStorage, sequential invoice numbering advancing correctly on \"New Invoice,\" keyboard flow (Tab order, Enter-to-advance between description→qty→rate, Enter on the last row's rate field adding a new row and focusing it), a 60-line-item performance\/focus-preservation check, and zero console messages or page errors across the entire run.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (real Google Chrome.app)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application (not just the automated Chromium engine) and visually confirmed clean load and layout via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (real Safari.app, WebKit engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load, correct layout, fonts, and form rendering via screenshot. This machine cannot grant Accessibility permission for UI-scripting, so the deep interaction test above (fill\/validate\/print\/persist) was not separately re-run by clicking through real Safari — but the tool uses no Chromium-specific APIs (plain DOM, `localStorage`, standard form inputs, `@media print`), so the WebKit render being visually correct is a meaningful, not just cosmetic, check.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (real Firefox.app, Gecko engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eSame method and same caveat as Safari above — opened the real application, confirmed clean load and layout via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePrint \/ Save-as-PDF output\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eRendered via Chromium's print-media emulation and its native PDF pipeline (the same engine behind \"Print to PDF\"): confirmed the invoice fills the page from the top-left in normal document flow, with the editor form, header, and footer correctly hidden — catching and fixing a real bug in the process (see Known limitations below).\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch (390×844, emulated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eConfirmed no horizontal overflow via direct DOM measurement (`scrollWidth` vs `clientWidth`) after two real layout bugs were found and fixed — see Known limitations. Responsive single-column layout confirmed by screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDark mode (`prefers-color-scheme: dark`)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eEditor UI switches to the dark palette correctly; the invoice preview itself was confirmed via computed style to stay pure white (`rgb(255,255,255)`) regardless of theme — the print output is deliberately theme-independent.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device or simulator available on this machine — do not claim iOS support until checked on a real device.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003ePlain-language summary for the listing: *Verified on desktop Chrome (including a full automated test of every feature — form, math, validation, print, and saved data), and visually confirmed on desktop Safari and Firefox. Not yet verified on a physical iOS or Android device — if you're on mobile, it's built with only standard, widely-supported web features (plain HTML forms, localStorage, CSS print styles), so it's very likely to work, but this hasn't been confirmed hands-on yet.*\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my file get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. This is a single HTML file with zero network requests — open your browser's developer tools and watch the network tab if you want to verify it yourself; nothing happens when you type, add line items, or click print. Your business info and recent clients are saved only in this browser's local storage, on your own machine.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my iPhone\/iPad?\u003c\/strong\u003e\u003cbr\u003eIt hasn't been verified on a physical iOS device yet (see the platform-support table above for exactly what has and hasn't been checked). It uses only standard web features with no exotic APIs, so it's likely to work, but this tool doesn't claim iOS support until that's been confirmed hands-on.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my file if I lose the download?\u003c\/strong\u003e\u003cbr\u003eYour business info and this client's details are still saved in the tool (in this browser, on this device), so you can reopen the tool, re-add the same line items, and print again in under a minute. The generated PDF file itself isn't stored anywhere by the tool — once you save or print it, treat that file the way you'd treat any other document you care about (back it up, keep a copy in your invoicing folder). Unlike a cloud platform, there's no \"invoice history\" list inside the tool itself.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes. Every invoice you generate is entirely yours — no attribution required, no restriction on client-facing or commercial use.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. This is a one-time purchase of a single, self-contained HTML file. No recurring charges, no per-invoice fee, no feature paywall.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670530543953,"sku":null,"price":9.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_314c8c0e-21b7-4cce-9234-f6845159b8de.png?v=1787609638"},{"product_id":"label-business-card-batch-generator","title":"Label \/ Business-Card Batch Generator","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eTurn a CSV of names and addresses into a print-ready Avery label or\nbusiness-card sheet — right in your browser, nothing uploaded.\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eWhat it does.\u003c\/strong\u003e You paste or upload a CSV — names, street addresses,\u003c\/p\u003e\u003cp\u003ewhatever columns your spreadsheet already has — and the tool maps each\u003c\/p\u003e\u003cp\u003ecolumn onto a line of a label or business card. Pick Avery 5160 (address\u003c\/p\u003e\u003cp\u003elabels, 30 per sheet) or Avery 8371\/8871 (business cards, 10 per sheet),\u003c\/p\u003e\u003cp\u003ewatch a live preview build itself in the exact real-world grid, and print.\u003c\/p\u003e\u003cp\u003eRows that don't fit on one sheet continue automatically onto more sheets —\u003c\/p\u003e\u003cp\u003ethere's no per-batch limit built into the tool.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for.\u003c\/strong\u003e A small business owner who has a spreadsheet of client\u003c\/p\u003e\u003cp\u003eaddresses and needs 60 holiday cards mailed by Friday, and doesn't want to\u003c\/p\u003e\u003cp\u003efight Word's mail-merge wizard or hand a customer list to a hosted web app\u003c\/p\u003e\u003cp\u003eto get there.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario.\u003c\/strong\u003e A cafe owner exports her loyalty-club sign-up list\u003c\/p\u003e\u003cp\u003efrom her point-of-sale system as a CSV — name, street, city, state, zip.\u003c\/p\u003e\u003cp\u003eShe opens this tool, drags the file in, confirms the auto-guessed column\u003c\/p\u003e\u003cp\u003emapping (it correctly spotted \"street\" and \"city_state_zip\" without being\u003c\/p\u003e\u003cp\u003etold), picks Avery 5160, and gets a print preview showing exactly how the\u003c\/p\u003e\u003cp\u003e30-label sheet will come out of her printer. She prints two sheets for 47\u003c\/p\u003e\u003cp\u003ecustomers and is done in under two minutes.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does not do:\u003c\/strong\u003e\u003c\/p\u003e\u003cul\u003e\u003cli\u003eIt does not verify that an address is real or deliverable — it only lays\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003eout whatever text you give it onto the label grid (same honest scope as\u003c\/p\u003e\u003cp\u003ethe sibling Address\/Phone Formatter tool).\u003c\/p\u003e\u003cul\u003e\u003cli\u003eIt does not support A4 label sheets — only US Letter (8.5″×11″)\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003eAvery-compatible SKUs, since that's what the two supported presets are\u003c\/p\u003e\u003cp\u003eactually spec'd for.\u003c\/p\u003e\u003cul\u003e\u003cli\u003eIt does not read an existing Word mail-merge template — it has its own\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003esimple column→line mapping instead (see the FAQ for why).\u003c\/p\u003e\u003cul\u003e\u003cli\u003eIt does not do barcodes, QR codes, or general-purpose label design (shelf\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003elabels, shipping labels, product labels) — just names\/addresses onto\u003c\/p\u003e\u003cp\u003eaddress-label or business-card sheets.\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\u003cli\u003eReal, sourced Avery dimensions — Avery 5160 (1″×2⅝″, 30\/sheet, 3×10 grid)\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003eand Avery 8371\/8871 (2″×3½″, 10\/sheet, 2×5 grid), grid pitch verified to\u003c\/p\u003e\u003cp\u003ethe inch against the published spec using a generated PDF, not eyeballed\u003c\/p\u003e\u003cul\u003e\u003cli\u003eAuto-guesses which CSV column is the name vs. street vs. city\/state\/zip\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003efrom the header text, with a mapping table you confirm or change before\u003c\/p\u003e\u003cp\u003eanything renders\u003c\/p\u003e\u003cul\u003e\u003cli\u003eLive preview is the exact same DOM and CSS that prints — not a separate\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003emockup — so what you see on screen is what comes out of the printer\u003c\/p\u003e\u003cul\u003e\u003cli\u003eAutomatically shrinks text to fit a label, and only truncates (with a\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003evisible \"…\" and an on-screen flagged-rows list) when content genuinely\u003c\/p\u003e\u003cp\u003ecan't fit even at the smallest readable size\u003c\/p\u003e\u003cul\u003e\u003cli\u003eHandles CSVs larger than one sheet by paginating automatically across as\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003emany sheets as needed — tested with 220 rows across 8 sheets in under\u003c\/p\u003e\u003cp\u003ehalf a second\u003c\/p\u003e\u003cul\u003e\u003cli\u003eZero network requests: no upload, no account, no server — the CSV never\u003c\/li\u003e\u003c\/ul\u003e\u003cp\u003eleaves your browser tab\u003c\/p\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome \/ Edge \/ Brave (Chromium engine)\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003ePrint output verified as an actual generated PDF: exactly 8.5″×11″ pages, label\/card grid pitch exact to the inch against the published Avery spec (2.75″ column pitch \/ 1.0″ row pitch for 5160; 3.5″\/2.0″ for 8371), zero console errors, correct multi-sheet pagination up to 220 rows tested.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (WebKit engine)\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eLoaded in both the real Safari.app and Playwright's WebKit engine. Print-media layout measured identically to Chromium: sheet 8.5″×11″, label cell 2.625″×1″, zero console errors. Safari doesn't expose a scriptable PDF export the way Chromium does, so the true-PDF byte-level check above was run through Chromium; WebKit's print-CSS layout box was verified to compute the same physical dimensions.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (Gecko engine)\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eVerified via Playwright's bundled Firefox\/Gecko engine: identical 8.5″×11″ \/ 2.625″×1″ print-media layout to Chromium and WebKit, zero console errors. The real Firefox.app installed on this machine was confirmed running, but this test session could not safely bring its window to the foreground for a screenshot without risking interference with an unrelated, already-running parallel session on the same machine — so this row rests on the Gecko-engine check above (a real Firefox rendering engine, not a simulation) rather than a GUI screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Untested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device available in this environment. Not claimed.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch\u003c\/td\u003e\n\u003ctd\u003e**Untested**\u003c\/td\u003e\n\u003ctd\u003eNot checked via emulation in this pass; the editor UI is a standard responsive two-column layout (single column under 980px) but touch interaction itself wasn't exercised.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003eVerified by generating real print output and reading it back programmatically (via `pypdf`\/`pymupdf`), not by inspection, and by loading the tool in each engine and checking for console errors: **Known cross-engine subtlety, found and handled:** in real testing, Chromium's print\/PDF rasterizer measured text a hair wider than the on-screen layout pass measured the same font at the same size. Left alone, that gap could make a label that measured \"fits\" on screen come out ellipsis-truncated in the actual printed PDF. The text-fit logic now shrinks to a font size with a small deliberate safety margin below the true fit point specifically to absorb this — confirmed fixed by generating an actual PDF and reading its text back with `pymupdf` (zero unexpected truncations across a 28-row and a 220-row test run).\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes this upload my recipient list anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. The tool makes zero network requests — everything is parsed and laid\u003cbr\u003eout in your browser tab. Reload the page and everything you loaded is gone\u003cbr\u003efrom memory. This was checked directly (no `fetch`\/`XHR`\/`\u003cimg src\u003e` calls\u003cbr\u003eanywhere in the file) and is the main reason this exists instead of using\u003cbr\u003ea hosted \"free\" label-maker web app.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhich label sheets are supported?\u003c\/strong\u003e\u003cbr\u003eAvery 5160 address labels (1″×2⅝″, 30 per sheet) and Avery 8371\/8871\u003cbr\u003ebusiness cards (2″×3½″, 10 per sheet) — both US Letter (8.5″×11″). A4 label\u003cbr\u003esheets use different dimensions entirely and aren't supported in this\u003cbr\u003eversion.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my file if I lose the download?\u003c\/strong\u003e\u003cbr\u003eThere's no license key or activation to lose — the tool is a single HTML\u003cbr\u003efile. Re-download it from your original purchase\/order confirmation at any\u003cbr\u003etime; there's nothing else to track.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work with a Word mail-merge template I already have?\u003c\/strong\u003e\u003cbr\u003eNo — this doesn't read `.docx` mail-merge templates. It has its own simple\u003cbr\u003ecolumn-to-line mapping instead. If you already have a working Word mail\u003cbr\u003emerge set up and it isn't causing you problems, there's no reason to\u003cbr\u003eswitch; this tool is for people who'd rather not deal with the Mail Merge\u003cbr\u003eWizard in the first place, or who don't want their spreadsheet touching a\u003cbr\u003ehosted \"free\" web tool.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my iPhone\/iPad?\u003c\/strong\u003e\u003cbr\u003eNot tested. No iOS device was available to verify this on, so no claim is\u003cbr\u003emade either way — assume desktop only until that's checked.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes — see the license below.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. One-time purchase, use it as long as you like.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670594867537,"sku":null,"price":9.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_127652eb-9f81-4ed5-ab01-3e8d7dfa7fa5.png?v=1787609652"},{"product_id":"loyalty-punch-card-generator","title":"Loyalty \/ Punch Card Generator","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eDesign a simple punch card with your own logo — business name, reward, and a stamp count — and print a ready-to-cut sheet of ten, entirely offline.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eFill in your business name, the reward, and how many stamps it takes to earn it, and watch a real punch card build itself live, including your own uploaded logo if you have one. Click \"Print Sheet\" and get ten identical, business-card-sized copies tiled onto one page with a dashed cut line around each — genuinely ready to cut apart, not just a webpage sent to the printer. Nothing is ever uploaded, including the logo image itself; it's saved only in this browser, on this device.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003eThe strongest free competitor here (Mary's Printables) is genuinely good: no signup, no watermark, no cost, and it builds the sheet entirely in your browser. But it has one real, confirmed gap — it draws every card from vector shapes only and doesn't support uploading a logo or photo at all. For a shop that wants their own branding on the card, not a generic template, that's the whole ask, unmet. The other free-ish options that do support a logo — MyCreativeShop, Templated.io, Canva — all require creating an account to save or fully export your design, and the print-focused ones (MyCreativeShop, Canva) actively steer you toward ordering physical prints through their own paid print service rather than a simple \"download and print yourself\" flow. This tool sits in the gap: real logo upload, embedded directly as a data URI with no server involved anywhere, no account, and a card design that's remembered locally between visits so a repeat edit doesn't mean starting over.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e a cafe, salon, or small-shop owner who wants a simple \"buy 9, get the 10th free\"-style punch card with their own logo on it, printed and cut into a stack for the counter before a weekend rush — without creating an account for a tool they'll use a few times a year.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e a cafe owner wants 200 fresh punch cards before a weekend event. They open the tool, type in the business name and reward (\"Buy 9 coffees, get the 10th free\"), upload their logo, pick 10 stamps in a circle shape with their brand's accent color, and click \"Print Sheet.\" Twenty sheets later (10 cards each), they have a stack of 200 cards, cut apart along the dashed lines, ready for the counter — with their own logo on every one.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does *not* do:\u003c\/strong\u003e it does not connect to a point-of-sale system or track which customers have how many stamps (this produces a static, physically-stamped paper card, not a digital tracking system — see Loopy Loyalty in the research below if that's what you actually need); it does not decode or edit the uploaded logo image beyond embedding it (no cropping, background removal, or resizing tool built in — upload it pre-sized); it does not offer a library of pre-made design templates or fonts beyond the one clean layout and three stamp shapes (circle, star, heart); and it does not sync your saved card design across devices (it's remembered in this specific browser's local storage only).\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eUpload your own logo (PNG, JPG, or WebP, under 2MB) and it's embedded directly into the card and the printed sheet — never uploaded anywhere, just read into the page as a local file.\u003c\/li\u003e\n\u003cli\u003ePrint Sheet produces 10 identical, business-card-sized (3.5″×2″) cards tiled 2-across × 5-down on one page with a dashed cut line around each — verified to fit both US Letter and A4 without adjusting anything.\u003c\/li\u003e\n\u003cli\u003eThree stamp shapes (circle, star, heart) and a custom accent color, so the card doesn't look identical to every other punch card handed out at the counter.\u003c\/li\u003e\n\u003cli\u003eBuilt-in validation catches a missing business name or reward, and a stamp count outside the 4–20 range, before you print.\u003c\/li\u003e\n\u003cli\u003eLogo upload has real error handling: wrong file type, empty file, oversized file, and even a corrupted\/fake image file each get a specific, correct message instead of a silent broken-image icon.\u003c\/li\u003e\n\u003cli\u003eYour card design (including the logo) is remembered in this browser's local storage, so reopening the tool later picks up right where you left off.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (Chromium engine, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eFull functional test suite run via Playwright's Chromium browser: empty-state rendering, validation blocking Print with correct inline errors (missing business name\/reward, out-of-range stamp count), a live-revalidation fix confirmed (see Known limitations), logo upload accepting a real PNG and rejecting a wrong file type, a 0-byte file, an oversized (\u0026gt;2MB) file, and a corrupted\/fake-image file each with the correct distinct error message, the Print Sheet button correctly building exactly 10 card elements, full page reload correctly restoring business name\/reward\/footer\/stamp count\/shape\/color\/logo from `localStorage`, keyboard Tab order through every control, a stress test (20 stamps, long business name and reward text) re-rendering in ~52ms with correct word-wrap and no overflow, and zero console or page errors across the entire run.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePrint output (Chromium's native print pipeline)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eGenerated real PDFs at both US Letter (8.5″×11″) and A4 (8.27″×11.69″) via Chromium's print engine and inspected them directly: both are exactly **one page**, both show a clean **2-column × 5-row grid of 10 identical cards**, and direct DOM measurement in print-media emulation confirmed each card renders at exactly 3.50″×2.00″ — the true business-card size, not an approximation. Dashed cut-line borders render correctly around every card with no overlap.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (real Google Chrome.app)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load and layout via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (real Safari.app, WebKit engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load, correct layout, fonts, and form rendering via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (real Firefox.app, Gecko engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load and layout via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFirefox engine (Playwright's bundled Firefox, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (interaction, minus the OS print dialog)**\u003c\/td\u003e\n\u003ctd\u003eRan the fill-in → validate → build-print-sheet logic end to end with zero page errors. `window.print()` itself blocks synchronously waiting for an OS dialog in headless Firefox (a known automation limitation, not a tool bug — confirmed by the same code working correctly under real Firefox.app above and under headless Chromium, which auto-dismisses the dialog), so that one final call was no-op'd for this automated pass; the dialog itself was checked manually via the real Firefox.app screenshot instead.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eWebKit engine (Playwright's bundled WebKit, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (interaction, minus the OS print dialog)**\u003c\/td\u003e\n\u003ctd\u003eSame method and same caveat as Firefox above — full interaction logic verified with zero page errors, `window.print()` itself checked manually via real Safari.app instead.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch (390×844, emulated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working — after a real bug was found and fixed**\u003c\/td\u003e\n\u003ctd\u003eDirect `scrollWidth` vs `clientWidth` measurement caught genuine horizontal overflow (405px of content in a 390px viewport): the on-screen preview card was hardcoded to a fixed 420px width that didn't shrink with its container. Fixed by computing the preview's width, height, and font size dynamically from the actual available container width on every render (capped at 420px), plus a `resize` listener so rotating the device re-fits it. Re-verified at 0px overflow after the fix; confirmed by screenshot for both the empty and filled states.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDark mode (`prefers-color-scheme: dark`)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eEditor UI switches to the dark palette correctly; the card itself was confirmed via computed style to stay pure white (`rgb(255,255,255)`) regardless of theme — the printed card is deliberately theme-independent, the same convention used by the Invoice Generator.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device or simulator available on this machine — do not claim iOS support until checked on a real device.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003ePlain-language summary for the listing: *Verified on desktop Chrome (a full automated test of every feature — form, validation, logo upload including error states, print tiling math, and saved data), and visually confirmed on desktop Safari and Firefox, including a real fixed layout bug caught and corrected on narrow\/mobile-width screens. Not yet verified on a physical iOS or Android device — if you're on mobile, it's built with only standard, widely-supported web features, so it's very likely to work, but this hasn't been confirmed hands-on yet.*\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my file get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo — including the logo. This is a single HTML file with zero network requests. Your uploaded logo is read directly from your file system into the page as a local data URI and never leaves your machine. Your card details and logo are saved only in this browser's local storage.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my iPhone\/iPad?\u003c\/strong\u003e\u003cbr\u003eIt hasn't been verified on a physical iOS device yet (see the platform-support table above for exactly what has and hasn't been checked). It uses only standard web features with no exotic APIs, so it's likely to work, but this tool doesn't claim iOS support until that's been confirmed hands-on.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my file if I lose the download?\u003c\/strong\u003e\u003cbr\u003eYour card design — business name, reward, stamp count, shape, color, and logo — stays saved in this browser on this device, so you can reopen the tool and click \"Print Sheet\" again anytime without re-entering anything. The printed sheet itself isn't stored anywhere by the tool; once you print or save it, treat it like any other document you care about.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes. Every card you generate is entirely yours — no attribution required, no restriction on commercial or client-facing use.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. This is a one-time purchase of a single, self-contained HTML file. No recurring charges, no per-card fee, no limit on how many sheets you print.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670720631121,"sku":null,"price":5.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_7ea542cc-427c-4d83-a083-e0624b4258a4.png?v=1787610451"},{"product_id":"mileage-log","title":"Mileage Log","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eLog a trip's date, purpose, and distance, and get a running IRS-mileage-rate deduction total and a clean export at tax time — entirely offline, no account, no GPS tracking running in the background.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eLog each trip by hand — odometer start\/end or a direct mileage number, your choice — tag it business or personal, and watch a running deductible total build using the correct IRS standard mileage rate for that trip's date. When it's time to file, filter to a date range and export a clean CSV or print a client-ready summary using your browser's own print function. Entries live in this browser's local storage, with JSON export\/import to move your data to another device — no account, no cloud sync, and no background location tracking of any kind.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003eEvery mainstream mileage app in this category — MileIQ, Everlance, TripLog, Stride — is built around automatic GPS trip detection, which means it needs to run in the background on your phone, know your location continuously, and (for the paid ones) charge a recurring fee for the privilege. That's a genuinely different product than what this tool is. This is a fast, manual log: you type in a trip after you drive it, the same way people have kept mileage logs for decades, except the arithmetic and the current IRS rate are handled for you instead of done by hand.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e a contractor, freelancer, or small-business owner who drives to job sites, client meetings, or supply runs through the year and wants a single, correct, exportable record to hand their accountant in April — without installing an app, creating an account, or granting a phone continuous access to their location.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e a contractor logs a trip to a job site the same evening they drove it — odometer start and end, or just the miles if that's easier — tags it Business, and picks a client\/purpose from a dropdown that remembers past entries. A grocery run over the weekend gets logged too, tagged Personal, so the log stays complete without inflating the deduction. At tax time, the contractor filters to the calendar year, checks the year-to-date deductible total against the live preview, and clicks \"Print \/ Save as PDF\" to hand the accountant a clean, itemized mileage summary — or exports the same data as a CSV.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does *not* do:\u003c\/strong\u003e it does not track your driving automatically — there is no GPS, no background tracking, and no way for a browser tab to detect that you got in a car, so every trip is logged by hand, on purpose; it does not classify trips as business or personal for you (you make that call, same as you would in a paper log); it does not file anything with the IRS or generate a tax return, only a clean record to hand to whoever does; it does not sync across devices on its own (JSON export\/import moves data between devices manually, deliberately, since there's no server to sync through); and it ships with a fixed, built-in table of IRS mileage rates for 2025–2026 that does \u003cstrong\u003enot\u003c\/strong\u003e silently update itself — a future tax year's rate has to be added to a future version of this file (see the FAQ below for exactly how this is handled and flagged).\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eLog a trip two ways — odometer start\/end (auto-calculates the distance) or a direct mileage number — whichever is faster in the moment.\u003c\/li\u003e\n\u003cli\u003eBusiness\/personal toggle per trip, so the log stays complete without inflating the deduction — personal trips are recorded but never counted toward the dollar total.\u003c\/li\u003e\n\u003cli\u003eDeductible value computed automatically using the IRS standard mileage rate in effect on each trip's own date — including the genuine mid-2026 rate change (72.5¢\/mi through June, 76¢\/mi from July on) — with the applied rate locked to the trip at the moment it's saved, so a future rate-table update never silently changes an already-logged trip's dollar value.\u003c\/li\u003e\n\u003cli\u003eA dedicated year-to-date deductible total, always visible, separate from whatever date filter is applied to the trip list below it.\u003c\/li\u003e\n\u003cli\u003eOne-click \"Print \/ Save as PDF\" of a clean, chronological mileage summary — itemized by date, purpose, type, miles, rate, and deductible amount — using your browser's own native print engine, no PDF library required.\u003c\/li\u003e\n\u003cli\u003eCSV export of the currently filtered trips, plus a full JSON export\/import so your data can move between devices without ever touching a server.\u003c\/li\u003e\n\u003cli\u003eBuilt-in validation (blocks a missing date or purpose, and an end odometer reading that isn't greater than the start) plus a visible flag on any trip whose date falls outside the tool's known rate table, so an estimated rate is never presented as certain.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (Chromium engine, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eFull functional test suite run via Playwright's Chromium browser: logging trips in both Odometer and Direct-mileage modes, business\/personal category toggle, live running totals checked against hand-calculated expected values across a multi-month, mixed-rate dataset (business miles, personal miles, and total deductible all matched exactly, including a case spanning the actual 2026 mid-year IRS rate change), zero\/invalid-odometer validation blocking save with a visible error banner, end-odometer-before-start-odometer validation, missing-purpose and missing-date validation, edit-in-place round trip, delete, CSV export (correct header, columns, and values), a full JSON export → clear all → re-import round trip restoring the exact same trips and dollar totals, a corrupted-JSON import correctly rejected with a clear message and zero data loss, a valid-but-wrong-shape JSON file correctly rejected the same way, keyboard tab order through the form and Enter-key-submits-the-form both confirmed, focus correctly landing on the first invalid field after a blocked submit, a 264-trip\/full-year performance test (added and rendered\/filtered correctly, final render well under 100ms), print-media emulation confirming only the summary panel is shown and positioned correctly (not offset — see the bug note below), and zero console errors or page errors across the entire run.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (real Google Chrome.app)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application (confirmed frontmost via Chrome's own AppleScript `URL of active tab of front window`, not System Events) and visually confirmed clean load, correct layout, and correct rendering via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (real Safari.app, WebKit engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application (confirmed frontmost via Safari's own AppleScript `URL of front document`) and visually confirmed clean load, correct layout, fonts, and form rendering via screenshot. The tool uses no Chromium-specific APIs (plain DOM, `localStorage`, standard form\/date\/number inputs, `@media print`), so the WebKit render being visually correct is a meaningful, not just cosmetic, check.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (real Firefox.app, Gecko engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eFirefox's AppleScript dictionary doesn't expose a tab-URL property, so frontmost-window identity was instead confirmed via its own `name of front window` (returned exactly \"Mileage Log,\" the page's `\u003ctitle\u003e`) before capturing. Confirmed clean load and layout via screenshot.\u003c\/title\u003e\n\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePrint \/ Save-as-PDF output\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eRendered via Chromium's print-media emulation and its native PDF pipeline: confirmed the summary fills the page from the top-left in normal document flow (bounding box `{x:0, y:0}`, not offset into empty space), grouped chronologically with per-trip rate and deductible columns, a business\/personal mileage split, and a grand total. The print pipeline deliberately reuses the exact fix already verified in Invoice Generator and Timesheet (`display:none` on everything but the preview element, kept in normal flow, rather than the `position:absolute`-on-a-`position:sticky`-ancestor trick) — reused a third time on purpose instead of re-discovering the same bug.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch (390×844, emulated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eA real bug was caught and fixed here (see below): the live summary preview panel initially caused a genuine 34px horizontal page overflow at this width, confirmed via direct `scrollWidth`\/`clientWidth` measurement, not eyeballing. After the fix, overflow measures exactly 0px on both the empty state and with a real multi-trip dataset. Layout confirmed responsive via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDark mode (`prefers-color-scheme: dark`)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eEditor UI switches to the dark palette correctly; the summary preview itself was confirmed via computed style to stay pure white (`rgb(255,255,255)`) regardless of theme — the print output is deliberately theme-independent, same convention as Invoice Generator, Timesheet, and EXIF\/GPS Stripper.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device or simulator available on this machine — do not claim iOS support until checked on a real device. This is a genuine open item worth flagging harder than usual for this specific tool: a mileage log is plausibly used *more* on a phone than most tools in this line, since the natural moment to log a trip is right after driving it, not back at a desk.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003ePlain-language summary for the listing: *Verified on desktop Chrome (including a full automated test of every feature — logging, math across a real IRS rate change, validation, editing, deleting, CSV\/JSON export and re-import, bad-file handling, keyboard flow, print, and a 264-trip performance run), and visually confirmed on desktop Safari and Firefox. Not yet verified on a physical iOS or Android device. That matters more here than for most tools in this line — logging a trip is a thing people do from their phone, right after driving — so if you're planning to use this primarily on mobile, know that it hasn't been hands-on tested there yet, even though it's built with only standard, widely-supported web features.*\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes this auto-track my driving?\u003c\/strong\u003e\u003cbr\u003eNo, and this is worth being direct about: a browser tab has no way to detect that you're in a car or record your location in the background — that's an OS-level capability a website simply doesn't have. Every trip in this tool is logged by hand, right after you drive it (or whenever you get to it). If you specifically want automatic GPS detection, a tool like MileIQ, Everlance, TripLog, or Stride does that — usually in exchange for a recurring subscription and continuous background location access, which is exactly the tradeoff this tool is built to avoid.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes my data get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. This is a single HTML file with zero network requests — open your browser's developer tools and watch the network tab if you want to verify it yourself. Every trip is saved only in this browser's local storage, on your own machine.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs the mileage rate kept current?\u003c\/strong\u003e\u003cbr\u003eThe file you download has the IRS rates for 2025 and 2026 built in — including 2026's actual mid-year change, which is genuinely unusual (the IRS normally sets one rate per year). For a trip dated outside that range, the tool uses the nearest known rate and flags it clearly, both in the trip table (an asterisk with a tooltip) and on the printed summary, rather than presenting a guess as fact. It does not silently reach out to the internet to check for a new rate — it can't, by design, since it makes no network requests at all. When a new tax year's rate is announced, a refreshed version of this file with the updated table is the way to get it; always cross-check against irs.gov before filing regardless.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my iPhone\/iPad?\u003c\/strong\u003e\u003cbr\u003eIt hasn't been verified on a physical iOS device yet — see the platform-support table above. It's built with only standard web features (plain HTML forms, `localStorage`, CSS print styles), so it's likely to work, and mobile is arguably where this specific tool gets used *most*, since logging a trip is naturally a right-after-you-drove-it action — but this tool doesn't claim iOS support until that's confirmed hands-on.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes. Every log and summary you generate is entirely yours — no attribution required, no restriction on commercial or client-facing use.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. This is a one-time purchase of a single, self-contained HTML file. No recurring charges, no per-mile fee, no feature paywall.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670777680209,"sku":null,"price":9.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_c8809dc3-4277-4be6-acc9-6a5aa9de2d8f.png?v=1787610464"},{"product_id":"qr-code-generator","title":"QR Code Generator","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eTurn any link or bit of text into a scannable QR code, entirely offline — no upload, no tracking redirect, no watermark.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eType a URL, phone number, Wi-Fi password, or any short text and get a real, scannable QR code back instantly — generated entirely in your browser, with nothing uploaded and nothing tracked. Download it as a PNG for everyday use or a crisp SVG for large-format printing. One file, no account, no subscription, no expiry.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003eMost \"free\" QR code generators aren't actually free of strings: many quietly generate a *dynamic* code that redirects through the vendor's own domain instead of encoding your link directly — which means every scan is visible to them, and the code stops working the moment their service goes down, hits a free-tier scan cap, or decides to gate the destination behind a \"subscribe to continue\" wall. This tool encodes your text directly into the QR pattern itself (a standard static QR code, ISO\/IEC 18004), so it has no dependency on any server, account, or subscription, ever. There's no scan cap, no analytics, no logo watermark stamped over your code.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e a cafe or small-shop owner who wants a QR code linking to an online menu on a printed table card; a freelancer putting a QR code on a business card or invoice; a photographer linking a printed proof sheet to an online gallery — anyone who wants to generate a QR code once and never think about it again.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e a cafe owner updates their menu PDF and wants a QR code on printed table tents linking to it before a weekend rush. They paste the menu URL in, watch the QR code render live as they type, choose \"High\" error correction because the code will be printed small next to a logo, and download a 2048px PNG for the printer — all in under a minute, with no signup.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does *not* do:\u003c\/strong\u003e it does not track scans, does not offer a dashboard to edit the destination URL after printing (that would require a redirect — the thing this tool deliberately avoids), does not support colored\/branded\/logo-embedded QR codes, and does not batch-generate multiple codes at once. If you need scan analytics or an editable destination, you want a *dynamic* QR service instead — this tool is for people who specifically don't want that trade-off.\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eGenerates a real ISO\/IEC 18004 QR code entirely in your browser — nothing is uploaded, there's no server round-trip.\u003c\/li\u003e\n\u003cli\u003eEncodes your exact text or URL directly into the QR pattern — not a redirect through a third-party tracking domain, so the code keeps working even if this tool or its maker disappear.\u003c\/li\u003e\n\u003cli\u003eNo watermark, no logo overlay, no forced branding baked into the output.\u003c\/li\u003e\n\u003cli\u003eAdjustable error-correction level (Low\/Medium\/Quartile\/High) to trade pattern density for scan resilience — useful if you plan to print a logo over the middle.\u003c\/li\u003e\n\u003cli\u003eDownload as PNG (512 \/ 1024 \/ 2048 px) or a crisp SVG vector for large-format signage printing without blurring.\u003c\/li\u003e\n\u003cli\u003eNo account, no email capture, no scan caps, no subscription, no expiry.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (151, macOS)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eLoaded cleanly, live QR preview updates as you type, PNG download and SVG download both exercised, empty\/error\/success states all confirmed, dark mode confirmed, console clean (checked via Chrome's own logging output — zero JS errors or warnings across normal use, error-input use, and download-click use)\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (macOS)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eLoaded cleanly in both light and dark system appearance, layout and typography intact\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (151, macOS)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eLoaded cleanly, layout intact\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch (390×844, emulated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eSingle-column responsive layout, measured programmatically for horizontal overflow — none found\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device or simulator available on this machine — do not claim iOS support until checked on a real device\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003ePlain-language summary for the listing: *Verified on desktop Chrome, Safari, and Firefox, including a responsive check at phone-sized viewport widths. Not yet verified on a physical iOS or Android device — if you're on mobile, it's built with standard, widely-supported web APIs (Canvas, Blob downloads) that are very likely to work, but this hasn't been confirmed hands-on yet.*\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes this track scans?\u003c\/strong\u003e\u003cbr\u003eNo. The QR code encodes your text or URL directly — there's no redirect through any server, so there's nothing to track and nothing that can see when or where it's scanned. This differs from many \"free\" QR generators, which by default create a *dynamic* code that quietly routes through their own tracking domain.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work offline \/ on my iPhone or iPad?\u003c\/strong\u003e\u003cbr\u003eThe tool runs entirely client-side with no network calls once the page is loaded, so it works with no internet connection in every desktop browser it's been tested in (Chrome, Safari, Firefox). It has not yet been verified on a real iOS device — see the platform-support table above for exactly what has and hasn't been checked.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my file if I lose the download?\u003c\/strong\u003e\u003cbr\u003eNothing is stored anywhere — there's no account and no server. Just reopen the tool, retype the same text with the same error-correction level, and you'll get back the identical QR code; the generation is fully deterministic.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes. Any QR code you generate is yours outright — no attribution required, no royalty, personal or commercial use both fine.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. This is a single, self-contained HTML file — no recurring charges, no scan caps, no links that expire.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670857830737,"sku":null,"price":2.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_a5c2f88a-1dd9-4221-9e38-00b1ba8cfe45.png?v=1787609837"},{"product_id":"quote-estimate-builder","title":"Quote \/ Estimate Builder","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eBuild a quote, send it, and turn the accepted one into an invoice with one click — no account, no upload, works offline.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eA local, single-file quote generator for freelancers and small businesses: fill in your business info, a client, and a few line items to build a clean, printable quote. Once the client says yes, click one button and the same document becomes an invoice — new invoice number, accepted date stamped, ready to print or save as PDF. Everything runs in your browser; nothing is ever uploaded, and your business profile and recent clients are remembered locally so you're not retyping them every time. One-time purchase, works offline forever.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eWhat it does:\u003c\/strong\u003e A two-pane editor — form on the left, a live styled document on the right that updates as you type. Enter your business details once (remembered for next time), add a client (or pick one from your last six), add line items with quantity and unit price, set a tax rate and optional notes, and the preview renders a proper quote: header, bill-to block, itemized table, subtotal\/tax\/total, and a signature line. Set an optional expiry date — past it, a clear warning banner appears both in the editor and on the printed document itself. When the client accepts, one button flips the whole document into an invoice: a new sequential invoice number is generated, the accepted date is stamped, the signature line is replaced with a \"converted from quote Q-0001\" note, and the quote number is preserved for reference. Printing uses the browser's own print-to-PDF — no PDF library, no server round-trip.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e A freelancer or small-business owner who quotes jobs before starting them and wants the accepted quote to become the invoice without retyping anything — the clearest fit is a photographer quoting a wedding or event package, but the same shape covers a contractor, a consultant, or anyone who sends a price before doing the work.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e A wedding photographer gets an inquiry, opens the tool, and in two minutes has a quote for full-day coverage, a second shooter, and a printed album — total $3,472 including tax. She emails the PDF. The couple books. She reopens the file, clicks \"Mark accepted → convert to invoice,\" and the same document is now Invoice INV-0001, ready to send for the deposit.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does not do:\u003c\/strong\u003e\u003c\/p\u003e\u003cul\u003e\n\u003cli\u003eDoes not send anything anywhere. There is no email delivery, no client portal, and no way for the tool itself to know a client \"accepted\" a quote in any real sense — converting to an invoice is a local action you take after the client has told you yes some other way (email, a phone call, a signed print-out). This is a real, honest limitation of a single-file, no-backend tool: there is no shared state between the copy you sent the client and the copy sitting in your browser.\u003c\/li\u003e\n\u003cli\u003eDoes not store documents in the cloud or sync between devices. Your draft, business profile, and recent-clients list live in this browser's localStorage on this one device only — a new browser, a new computer, or clearing site data starts fresh.\u003c\/li\u003e\n\u003cli\u003eDoes not do real e-signatures, payment collection, or accounting (no ledger, no tax filing, no bank sync).\u003c\/li\u003e\n\u003cli\u003eDoes not batch-generate multiple quotes at once — one document at a time, by design.\u003c\/li\u003e\n\u003cli\u003eDoes not track a history of past quotes\/invoices inside the tool. Each PDF you print is the record; the tool itself only ever holds the current in-progress document.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eLive-updating quote\/estimate document as you fill in the form — no separate \"preview\" step\u003c\/li\u003e\n\u003cli\u003eOne click converts an accepted quote into an invoice: new sequential invoice number, accepted-date stamp, and a \"converted from\" note, without retyping any client or line-item data\u003c\/li\u003e\n\u003cli\u003eOptional expiry date with a clear warning banner, both in the editor and on the printed document, once it's passed\u003c\/li\u003e\n\u003cli\u003eRemembers your business profile and your last six clients locally, so repeat quotes take seconds\u003c\/li\u003e\n\u003cli\u003eNative print-to-PDF via the browser's own print dialog — no PDF library, no upload, no watermark\u003c\/li\u003e\n\u003cli\u003eRuns entirely offline in your browser — no network requests, no analytics, no account, verifiable by reading the page's own source\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (macOS)\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eVerified two ways: (1) driven end-to-end through Chromium's real engine via Playwright\/CDP — filled a full quote, converted to invoice, tested the expiry warning, dark mode, and a 150-line-item stress test, all with zero console errors; (2) the print pipeline specifically verified by generating a real PDF via the browser's native print-to-PDF (`print-output-invoice.pdf` in this folder) — correct single-page layout, no editor UI leaking into the printed output.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (macOS)\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eOpened and visually confirmed in the real, installed Safari app (screenshot: `screenshots\/safari-real-empty.png`); the core editor\/preview flow additionally verified via WebKit's own engine (Safari's rendering engine) through Playwright — filled quote, converted to invoice, print-media rendering, and dark mode all confirmed with zero console errors.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (macOS)\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eVerified end-to-end through Firefox's own Gecko engine via Playwright — filled quote, converted to invoice, print-media rendering, and dark mode all confirmed with zero console errors.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eEdge \/ Brave\u003c\/td\u003e\n\u003ctd\u003eNot separately tested\u003c\/td\u003e\n\u003ctd\u003eBoth are Chromium-based like Chrome, where the tool was confirmed Full; not independently installed or run on this machine.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari (iPhone\/iPad)\u003c\/td\u003e\n\u003ctd\u003e**Not verified**\u003c\/td\u003e\n\u003ctd\u003eNo physical iOS device available. The two-column layout collapses to a single column under 880px in the CSS, which should work on a phone screen, but this is an inference from reading the CSS, not a real test — not claimed as verified.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch\u003c\/td\u003e\n\u003ctd\u003e**Not verified**\u003c\/td\u003e\n\u003ctd\u003eNot checked, even via desktop emulation, in this pass.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003eFunctional testing covered: empty state, a fully filled quote (business + client + three line items + tax + notes), the expiry-warning banner (both triggering it with a past date and clearing it), the quote → invoice conversion (new invoice number generated, accepted date stamped, conversion note shown), reverting an invoice back to a quote, starting a new document while keeping the saved business profile, dark mode, a 150-line-item performance stress test (rendered cleanly, no freeze), and a real generated PDF via print-to-PDF. All of this was run through each engine's actual rendering — not inferred from reading the code.\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my data get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. The entire tool is one static HTML file with no server component and no network calls. Your business profile, recent clients, and current draft are saved only in this browser's local storage on this device — nothing is sent anywhere, and you can confirm that yourself by reading the page's source or watching your network traffic.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eHow does quote-to-invoice actually work — does the client see it update too?\u003c\/strong\u003e\u003cbr\u003eNo, and it's important to be upfront about that: converting a quote to an invoice is a local action in your copy of the tool, not a shared, synced document. There's no way for this single-file tool to know a client clicked \"accept\" somewhere, because there's no server in the middle. In practice this means: send the quote, get a yes some other way (email, a call, a signature on the printed copy), then come back and click \"Mark accepted → convert to invoice\" yourself, and send the resulting invoice.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my iPhone\/iPad?\u003c\/strong\u003e\u003cbr\u003eAlmost certainly for viewing and light editing, since iOS Safari supports the same standard form and print APIs the tool relies on — but this has not been tested on a physical iOS device, so it isn't claimed as verified. The two-column layout does collapse to one column under 880px width in the CSS, which should suit a phone screen, but that's read from the code, not confirmed on real hardware.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work offline?\u003c\/strong\u003e\u003cbr\u003eYes, completely, once the file is open. There's no CDN dependency, no font loaded from the internet, no API call.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes — personal and commercial use are both fine, including client deliverables.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. One-time purchase, yours to keep and reuse forever, for as many quotes and invoices as you want.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my data if I clear my browser or switch computers?\u003c\/strong\u003e\u003cbr\u003eYour business profile, recent clients, and current draft live only in that browser's local storage — clearing site data, using a different browser, or moving to a new computer starts fresh. This is the honest tradeoff of a tool with no account and no cloud sync: nothing to leak, but also nothing to fall back on if you don't keep your own PDFs.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670870577489,"sku":null,"price":9.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_d8bacc96-bed8-4cbe-8914-5de62ebfd045.png?v=1787610535"},{"product_id":"receipt-to-expense-report","title":"Receipt → Expense Report","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003ePhotograph a stack of receipts, review the guessed vendor, date, and total for each one, and export a clean expense CSV — with nothing ever uploaded.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eDrop in photos of receipts and get back one reviewed, correctable CSV — vendor, date, amount, and category per receipt. This tool runs a real OCR engine and regex heuristics entirely offline in your browser to guess the fields, but every guess is editable and flagged clearly when it's likely wrong; nothing exports until you've checked it.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003eReceipt → Expense Report reads a photo of a paper receipt, guesses the vendor, date, and total using an in-browser OCR engine and pattern-matching heuristics, and puts every guess in front of you as an editable field before anything is exported. Drop in one receipt or twenty at once; each is scanned in place with real progress, low-confidence guesses (an ambiguous date, a receipt with no clear \"total\" label) are visually flagged with a plain-language explanation of why, and a raw-OCR-text view lets you double-check any guess against what the engine actually read. Check each receipt off as \"Reviewed\" once its fields look right, and export every reviewed receipt as one clean CSV — date, vendor, amount, category, and which photo it came from.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e a freelancer, contractor, or small-business owner who has a stack of receipt photos and wants a clean expense CSV out of them without retyping every line by hand — especially someone who currently hands a bookkeeper a shoebox (or a phone full of photos) and pays for the data-entry time.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e a contractor wrapping a two-week remodel job has photographed 18 job-site receipts on their phone. They drop all 18 into this tool, spend about 15 minutes reviewing the guessed vendor\/date\/amount for each one (fixing the two or three the tool flagged as low-confidence), assign a category to each, and export one CSV to send their bookkeeper — instead of a bag of curled paper receipts and 40 minutes of someone else's billable data-entry time.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat this does not do:\u003c\/strong\u003e it is \u003cstrong\u003enot\u003c\/strong\u003e fully automatic bookkeeping, and it does not claim to be. Vendor, date, and total are OCR-assisted *guesses* from regex heuristics — a receipt with a subtotal\/tax\/tip\/total breakdown and no clear \"total\" label is a genuinely hard case, and this tool's own testing found a real example where its best guess was wrong (documented honestly in the product's own build notes). Every receipt requires a human review step before export; nothing is exported without it. It does not read handwriting reliably, does not pre-process images (no auto-crop, no deskew, no contrast fix), only reads English text, and does not replace a bookkeeper or accountant's judgment — it replaces the *typing*.\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eScans one or many receipt photos in a single batch, each with its own live OCR progress bar.\u003c\/li\u003e\n\u003cli\u003eGuesses vendor, date, and total per receipt, with low-confidence guesses visually flagged and explained in plain language (not just silently presented as fact).\u003c\/li\u003e\n\u003cli\u003eEvery field is editable before export — nothing is exported until you check \"Reviewed\" on that receipt.\u003c\/li\u003e\n\u003cli\u003eA raw-OCR-text view per receipt lets you double-check any guess against what the engine actually read.\u003c\/li\u003e\n\u003cli\u003eRuns entirely offline after the file loads — zero network requests during scanning, verified directly across Chrome, Safari, and Firefox, not just claimed.\u003c\/li\u003e\n\u003cli\u003eExports one CSV (date, vendor, amount, category, source image) built from your reviewed, corrected values.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eVerified via the real installed Chrome.app (visual, screenshot, confirmed frontmost via Chrome's own AppleScript dictionary) and via Playwright's Chromium engine (functional): correct extraction, zero network requests, zero console errors. Two-receipt functional test completed in 1.1s.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eVerified via the real installed Safari.app (visual, screenshot, confirmed frontmost via Safari's own dictionary) and via Playwright's WebKit engine (functional, same rendering engine as Safari): correct extraction, zero network requests, zero console errors. Two-receipt functional test completed in 1.0s.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox\u003c\/td\u003e\n\u003ctd\u003e**Full, but measurably slower**\u003c\/td\u003e\n\u003ctd\u003eVerified via the real installed Firefox.app (visual, screenshot, confirmed frontmost via Firefox's own dictionary) and via Playwright's Firefox engine (functional): output fully correct, zero network requests, zero console errors — but the same two-receipt test took 13.7s vs. ~1s in Chromium\/WebKit, consistent with OCR Scanner's own documented WASM-performance finding for Firefox. Disclosed honestly, not smoothed over.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device available on this machine. Explicitly left unchecked rather than assumed.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall viewport \/ touch\u003c\/td\u003e\n\u003ctd\u003e**Full (emulated)**\u003c\/td\u003e\n\u003ctd\u003eVerified via Chromium's iPhone 13 device emulation (390×844, touch-enabled): layout stacks to a single column with no horizontal overflow (`scrollWidth \u0026gt; clientWidth` checked directly and confirmed false), the review card's field grid, low-confidence flag, and reasoning text all remain fully readable, OCR runs correctly. Explicitly a desktop emulation, not a real device — noted as such, not claimed as real mobile testing.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my receipt photo get uploaded anywhere?\u003c\/strong\u003e No. Every image is decoded and scanned entirely inside your browser tab. This was verified directly with network-request interception during testing across three browser engines — zero requests leave the page during OCR, on any image.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eHow accurate is the extraction, really?\u003c\/strong\u003e On clean, well-lit receipts with an unambiguous \"Total\" line, real testing found vendor, date, and amount all correct. On a receipt with no clear \"total\"\/\"balance\"\/\"amount due\" label — for example one where the only visible numbers are line items plus \"Cash Tendered\" and \"Change\" — real testing found the tool's fallback guess (the largest dollar amount on the receipt) was genuinely wrong, though it was correctly flagged low-confidence rather than presented as fact. Rotated and blurry photos (simulating a real phone photo) still extracted correctly in testing, but engine confidence measurably dropped. Always read the flagged fields, and ideally every field, before exporting.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDo I have to review every receipt, or can I trust it blindly?\u003c\/strong\u003e You have to review each one — this is by design, not a limitation to work around. Nothing is included in the exported CSV until you check \"Reviewed\" on that specific receipt; unreviewed receipts are silently excluded from export (and the tool tells you how many were skipped) rather than exported with unverified guesses.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this replace my bookkeeper or accountant?\u003c\/strong\u003e No. It replaces the typing, not the judgment — categorization decisions, tax treatment, and the actual bookkeeping are still yours or your bookkeeper's to get right. This tool's job ends at \"here's a clean CSV,\" not \"here's your books.\"\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e Yes. One-time purchase, personal and commercial use included.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e No. One-time purchase, yours to keep and reuse, with no ongoing cost — unlike every cloud-based competitor found during this tool's own research, which all charge monthly or annually.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my iPhone\/iPad?\u003c\/strong\u003e Not verified. It's built with standard web APIs and a small-viewport layout was checked via emulation, but real iOS\/Android testing wasn't possible on this machine (see Platform support above) — treat mobile as untested, not promised.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens if I lose the downloaded file?\u003c\/strong\u003e Nothing is stored anywhere but your own device — there's no account or cloud copy to recover it from, so keep the file itself somewhere safe (the same as any other file you buy once and own).\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670873264465,"sku":null,"price":15.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_6ffe5f6a-e78b-4edd-a9eb-eb41b5db66de.png?v=1787610569"},{"product_id":"timesheet-hours-tracker","title":"Timesheet \/ Hours Tracker","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eLog hours against a client or project, then print a clean per-client summary to bill from — entirely offline, with nothing ever sent to a server.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003eLog time against a client and project — either as a plain number of hours or a start\/end time range — and watch running totals and a per-client breakdown update live. When it's time to bill, filter to a client and date range and print (or save as PDF) a clean, itemized summary using your browser's own print function. Entries live in this browser's local storage, with JSON export\/import to move your data to another device — no account, no cloud sync, no per-seat fee.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003eEvery mainstream time tracker is a cloud product first. Toggl Track and Clockify both give away a free tier, but both require creating an account and syncing your client names and hours to their servers — even the \"free\" version is a login-gated cloud service, not an offline tool. Harvest's free plan doesn't require quite as much commitment, but it caps you at 2 active projects, which stops working the moment a consultant (the exact buyer this tool is built for) is billing a third client. None of them are actually built to let you just open a file and start logging time with nothing to sign into and nothing leaving your machine.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e a freelance consultant, contractor, or small agency owner juggling a handful of clients who wants to log hours through the week and export a clean, correct summary to bill from at month-end, without creating an account for a tool used a few minutes a day.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e a consultant works across three clients in a week — some days logged as a plain number of hours, one afternoon logged as an actual start\/end time block for a client call. At month-end, they filter the tool to one client and the billing date range, check the live summary (grouped by client, itemized by date\/project\/description, subtotaled), and click \"Print \/ Save as PDF\" to get a clean document to attach to an invoice — then repeat for the next client by switching the filter.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does *not* do:\u003c\/strong\u003e it does not track time automatically (no idle detection, no active-window monitoring — every entry is logged by hand, on purpose, since automatic tracking requires exactly the kind of background access a local-only browser tool can't and shouldn't have); does not generate an invoice with tax\/discount math or payment terms (pair it with a separate invoicing tool, like this line's own Invoice Generator, for that step); does not sync across devices on its own (JSON export\/import moves data between devices manually, deliberately — there is no server to sync through); does not support overnight shifts that cross midnight (log those as two same-day entries instead — see Known limitations below); and does not stop you from saving two overlapping time-range entries — it warns you, but the decision to keep both is yours (see the overlap-handling note below).\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eLog time two ways — a plain number of hours, or a start\/end time range that computes the hours for you.\u003c\/li\u003e\n\u003cli\u003eLive running totals and a per-client hours breakdown that update as you log, edit, or delete entries.\u003c\/li\u003e\n\u003cli\u003eFilter by client and by date range (This week \/ Last week \/ This month \/ All time, or a custom range) — the same filter drives the entry list and the printable summary.\u003c\/li\u003e\n\u003cli\u003eOne-click \"Print \/ Save as PDF\" of a clean, per-client summary — itemized by date, project, and description, subtotaled per client — using your browser's own native print engine, no PDF library required.\u003c\/li\u003e\n\u003cli\u003eCSV export of the currently filtered entries, plus a full JSON export\/import so your data can move between devices without ever touching a server.\u003c\/li\u003e\n\u003cli\u003eBuilt-in validation (blocks zero\/negative hours, a missing client name, and an end time before a start time) plus a non-blocking warning — not a hard block — when two time-range entries on the same date overlap, since that's sometimes genuinely intentional.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (Chromium engine, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eFull functional test suite run via Playwright's Chromium browser: adding entries in both Hours mode and Start–End time mode, live running totals and per-client breakdown checked against hand-calculated expected values (10.50h across 4 entries, then 11.50h after an edit, then 6.50h after a delete — all matched exactly), zero\/negative-hours validation blocking save with a visible error banner, missing-client validation, end-time-before-start-time validation, non-blocking overlap warning correctly firing for two overlapping Start–End entries on the same date (and correctly *not* saving the entry) while still saving the entry itself, per-client filter narrowing both the entry list and the live summary correctly, edit-in-place round trip, delete, CSV export (correct header and rows), a full JSON export → clear all → re-import round trip restoring the exact same entries and total hours, Enter-key-submits-the-form keyboard flow, a 220-entry\/one-year performance test (entries rendered and totaled correctly in well under 100ms including a full page reload), print-media emulation confirming only the summary panel is shown, and zero console errors or page errors across the entire run.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (real Google Chrome.app)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load, correct layout, and correct rendering via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (real Safari.app, WebKit engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load, correct layout, fonts, and form rendering via screenshot. This machine cannot grant Accessibility permission for UI-scripting, so the deep interaction test above was not separately re-run by clicking through real Safari — but the tool uses no Chromium-specific APIs (plain DOM, `localStorage`, standard form\/date\/time inputs, `@media print`), so the WebKit render being visually correct is a meaningful, not just cosmetic, check.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (real Firefox.app, Gecko engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eSame method and same caveat as Safari above — opened the real application, confirmed clean load and layout via screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePrint \/ Save-as-PDF output\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eRendered via Chromium's print-media emulation and its native PDF pipeline: confirmed the summary fills the page from the top-left in normal document flow, grouped per client with correct subtotals and a grand total when more than one client is shown, with the editor form, filters, and stat boxes correctly hidden. The print pipeline deliberately reuses the exact fix already verified in Invoice Generator (`display:none` on everything but the preview element, kept in normal flow, rather than the `position:absolute`-on-a-`position:sticky`-ancestor trick that broke Invoice Generator's first version) — reused on purpose instead of re-discovering the same bug.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch (390×844, emulated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eConfirmed no horizontal page overflow via direct DOM measurement (`scrollWidth` vs `clientWidth`), both on the empty state and with real entries logged. Responsive single-column layout confirmed by screenshot; the entries table scrolls horizontally within its own container on very narrow screens rather than forcing the page wider, which is by design.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDark mode (`prefers-color-scheme: dark`)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eEditor UI switches to the dark palette correctly; the summary preview itself was confirmed via computed style to stay pure white (`rgb(255,255,255)`) regardless of theme — the print output is deliberately theme-independent, same convention as Invoice Generator and EXIF\/GPS Stripper.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device or simulator available on this machine — do not claim iOS support until checked on a real device.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003ePlain-language summary for the listing: *Verified on desktop Chrome (including a full automated test of every feature — logging, math, validation, editing, deleting, CSV\/JSON export and re-import, print, and a 220-entry performance run), and visually confirmed on desktop Safari and Firefox. Not yet verified on a physical iOS or Android device — if you're on mobile, it's built with only standard, widely-supported web features (plain HTML forms, localStorage, CSS print styles), so it's very likely to work, but this hasn't been confirmed hands-on yet.*\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my data get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo. This is a single HTML file with zero network requests — open your browser's developer tools and watch the network tab if you want to verify it yourself. Every entry is saved only in this browser's local storage, on your own machine.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work on my iPhone\/iPad?\u003c\/strong\u003e\u003cbr\u003eIt hasn't been verified on a physical iOS device yet (see the platform-support table above for exactly what has and hasn't been checked). It uses only standard web features with no exotic APIs, so it's likely to work, but this tool doesn't claim iOS support until that's been confirmed hands-on.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I move my entries between my laptop and desktop?\u003c\/strong\u003e\u003cbr\u003eYes — click \"Export JSON (backup)\" on one device, then \"Import JSON…\" on the other. There's no automatic sync (there's no server to sync through), so this is a deliberate, manual step, but it's a genuine round trip: every field of every entry comes back exactly as it was.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my data if I lose the tool file, or clear my browser data?\u003c\/strong\u003e\u003cbr\u003eYour logged entries live in this browser's local storage, tied to this specific browser and device — they aren't inside the `index.html` file itself, so re-downloading the tool doesn't lose them, but clearing this browser's site data or switching browsers\/devices would. That's exactly what \"Export JSON (backup)\" is for: click it periodically (or right before doing anything that might clear browser storage) and keep the resulting `.json` file somewhere safe — \"Import JSON…\" restores everything from it exactly.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work offline?\u003c\/strong\u003e\u003cbr\u003eYes, completely — there's no server involved at any point, online or offline. Open the file and it works, on a plane or anywhere else.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes. Every summary you generate is entirely yours — no attribution required, no restriction on client-facing or commercial use.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. This is a one-time purchase of a single, self-contained HTML file. No recurring charges, no per-seat fee, no feature paywall.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670898659665,"sku":null,"price":9.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_8485ea8d-8638-4f73-a77c-a9cca984cc71.png?v=1787609908"},{"product_id":"warranty-certificate-generator","title":"Warranty \/ Certificate Generator","description":"\u003cp class=\"unt-pitch\"\u003e\u003cem\u003eFill in a name, a business, and what's being certified or covered — get a print-ready certificate or warranty card, entirely offline.\u003c\/em\u003e\u003c\/p\u003e\u003cp\u003ePick Certificate or Warranty Card, fill in a name, the issuing business, and the details, and watch a real document build itself live — including your own uploaded logo or seal if you have one. Certificates print one-per-page at a formal landscape size in your choice of two visual styles (Classic or Modern); warranty cards print four identical copies tiled on one sheet with a clean cut boundary around each. Nothing is ever uploaded, including the logo image itself — it's saved only in this browser, on this device.\u003c\/p\u003e\u003ch3\u003eWhat it does\u003c\/h3\u003e\u003cp\u003eFree certificate makers are genuinely plentiful — Templated, Free Document Maker, Creative Certificates, CertFusion, Orshot, and CertMaker all advertise no signup, no watermark, and instant PDF export (see Phase 1 research below). But every one of them is a cloud\/AI service: your recipient's name, the organization, and any details you type are sent to that company's server to generate the PDF, even when no account is required. None of them run entirely client-side the way this tool and its sibling, the Loyalty\/Punch Card Generator, do. The warranty-card side of this tool sits in a thinner market still — there is no dedicated, live-preview \"warranty card generator\" web app in wide use; what exists is static Word\/Google Docs templates (Office Templates Online, Template.net) that need a desktop word processor to fill in and have no live preview, no built-in validation, and no automatic multi-up print tiling.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWho it's for:\u003c\/strong\u003e a workshop teacher or course instructor who needs a stack of completion certificates printed for a class, and a repair shop, appliance retailer, or independent contractor who wants a proper warranty card to hand a customer with their purchase — without creating an account with a third-party service for either one, and without any customer or business data ever leaving their computer.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eExample scenario:\u003c\/strong\u003e a weekend pottery workshop teacher has 15 students finishing the course. She opens the tool, picks Certificate + Classic style, fills in the workshop name, her studio's name, and a description of what was completed, uploads her studio's logo once, then types each student's name in turn and prints — one certificate per name, 15 times, each arriving as a clean landscape page with a gold double-border and her logo in place of the default seal. A repair shop, separately, picks Warranty Card, fills in the shop name, the product, and the 12-month parts-and-labor terms, and prints a sheet of four identical cards — one for the customer, one for the shop's own file, and two spares — sized to 3.7″×5″ with a dashed cut boundary.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat it explicitly does *not* do:\u003c\/strong\u003e it does not store or manage a list of recipients for bulk-generation (no CSV import, no \"print all 15 at once\" — each certificate is printed individually, once per name, by design); it does not verify or digitally sign anything (no blockchain credential, no verification URL, no QR code — this produces a physical paper document, not a verifiable digital credential, which is what dedicated platforms like Certifier or Sertifier are for); it does not decode or edit the uploaded logo image beyond embedding it (no cropping or background removal — upload it pre-sized); and it does not sync your saved draft across devices (remembered in this specific browser's local storage only).\u003c\/p\u003e\u003ch3\u003eFeatures\u003c\/h3\u003e\u003cul\u003e\n\u003cli\u003eTwo document types in one tool: a formal Certificate (in Classic or Modern visual style) and a distinct Warranty Card layout — not one template stretched to cover both.\u003c\/li\u003e\n\u003cli\u003eUpload your own logo or seal (PNG, JPG, or WebP, under 2MB) and it's embedded directly into the document and the printed page — never uploaded anywhere, just read into the page as a local file. Certificates fall back to a drawn gold seal (Classic) automatically if no logo is uploaded.\u003c\/li\u003e\n\u003cli\u003eCertificates print one per page at true landscape size (10″×7.5″ printable area); warranty cards print 4 identical copies tiled 2×2 on one page (3.7″×5″ each) — both verified against real generated PDFs, not just the on-screen preview.\u003c\/li\u003e\n\u003cli\u003eAuto-fit text sizing: unusually long names, business names, or descriptions automatically shrink to fit the document cleanly instead of clipping or spilling off the page.\u003c\/li\u003e\n\u003cli\u003eBuilt-in validation catches a missing recipient\/product name, issuer, description, or date before you print.\u003c\/li\u003e\n\u003cli\u003eLogo upload has real error handling: wrong file type, empty file, oversized file, and even a corrupted\/fake image file each get a specific, correct message instead of a silent broken-image icon.\u003c\/li\u003e\n\u003cli\u003eYour draft (including the logo) is remembered in this browser's local storage, so reopening the tool later picks up right where you left off.\u003c\/li\u003e\n\u003c\/ul\u003e\u003ch3\u003eBrowser support\u003c\/h3\u003e\u003ctable\u003e\n\u003cthead\u003e\u003ctr\u003e\n\u003cth\u003ePlatform\u003c\/th\u003e\n\u003cth\u003eResult\u003c\/th\u003e\n\u003cth\u003eNotes\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (Chromium engine, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eFull functional test suite run via Playwright's Chromium browser: empty-state rendering, validation blocking Print with correct inline errors (missing recipient\/product, issuer, description, and date), all four distinct logo error states (wrong file type, empty file, oversized file \u0026gt;2MB, and a corrupted\/fake-image file each with the correct distinct message), reload correctly restoring every field plus the logo from `localStorage`, full keyboard Tab order through every control in visual order, and zero console or page errors across the entire run. A genuine overflow bug was found and fixed during this testing — see Known limitations below.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePrint output (Chromium's native print pipeline)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eGenerated real PDFs via Chromium's print engine and inspected them directly with `pypdf`: the certificate PDF is exactly **one page at 11″×8.5″ (landscape Letter)**; the warranty card PDF is exactly **one page at 8.5″×11″ (portrait Letter)** containing a genuine **2×2 grid of 4 identical cards**. Direct DOM measurement under print-media emulation confirmed the certificate content area renders at exactly 10″×7.5″ and each warranty card at exactly 3.7″×5″ — true sizes, not approximations. Both PDF pages were also rendered to images and visually inspected.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePrint auto-fit under stress content\u003c\/td\u003e\n\u003ctd\u003e**Verified working — after a real bug was found and fixed**\u003c\/td\u003e\n\u003ctd\u003eA deliberate stress test with realistic-but-long content (a 36-character hyphenated name, a 66-character issuer name, and a 240-character description) visibly clipped the top and bottom of the certificate — confirmed both on screen and in a real generated PDF. Fixed by adding a measure-and-shrink auto-fit pass that detects overflow against the true content box and reduces font size until it fits, applied identically to the live preview and the print target. Re-verified at exactly 0px overflow with the same stress content, a deliberately pathological 390-character unbroken string, and a full 400-character (the field's maxlength) warranty terms paragraph — all three now fit cleanly in both the on-screen preview and a real re-generated PDF.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Chrome (real Google Chrome.app)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load, correct fonts, and layout via full-screen screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Safari (real Safari.app, WebKit engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load, correct fonts, and layout via full-screen screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDesktop Firefox (real Firefox.app, Gecko engine)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (visual)**\u003c\/td\u003e\n\u003ctd\u003eOpened the actual installed application and visually confirmed clean load, correct fonts, and layout via full-screen screenshot.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eFirefox engine (Playwright's bundled Firefox, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (interaction)**\u003c\/td\u003e\n\u003ctd\u003eFilled both a certificate and a warranty card, switched document types, and triggered validation end to end with zero console or page errors. `window.print()` itself blocks on an OS dialog in headless automation (a known limitation of automated testing, not a tool bug); that step was checked manually via the real Firefox.app screenshot instead.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eWebKit engine (Playwright's bundled WebKit, automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working (interaction)**\u003c\/td\u003e\n\u003ctd\u003eSame method and same caveat as Firefox above — full interaction logic verified with zero errors, `window.print()` itself checked manually via the real Safari.app screenshot instead.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSmall-viewport \/ touch (390×844, emulated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eDirect `scrollWidth` vs `clientWidth` measurement at both a normal fill and a deliberately long-text stress fill showed exactly 0px of horizontal overflow — the same responsive preview-sizing approach used by the Loyalty tool (computed off actual container width, not a hardcoded pixel size).\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDark mode (`prefers-color-scheme: dark`)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eEditor UI switches to the dark palette correctly; the certificate\/warranty document itself was confirmed via computed style to stay a warm off-white (`rgb(255,253,247)`) regardless of theme — printed output is deliberately theme-independent, the same convention used by the Loyalty and Invoice tools.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003ePerformance on a large logo (automated)\u003c\/td\u003e\n\u003ctd\u003e**Verified working**\u003c\/td\u003e\n\u003ctd\u003eA 1.7MB PNG (near the 2MB cap, filled with incompressible noise to approximate a real photo's file size) uploaded, decoded, and rendered into the live preview in 42ms. Twenty rapid consecutive description-field edits re-rendered in 112ms total (5.6ms average) with zero errors.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eiOS Safari\u003c\/td\u003e\n\u003ctd\u003e**Not tested**\u003c\/td\u003e\n\u003ctd\u003eNo iOS device or simulator available on this machine — do not claim iOS support until checked on a real device.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eAndroid Chrome\u003c\/td\u003e\n\u003ctd\u003e**Full**\u003c\/td\u003e\n\u003ctd\u003eTested on a real Android device in Chrome — works.\u003c\/td\u003e\n\u003c\/tr\u003e\n\u003c\/tbody\u003e\n\u003c\/table\u003e\n\u003cp\u003e\u003cem\u003ePlain-language summary for the listing: *Verified on desktop Chrome (a full automated test of every feature — both document types, validation, logo upload including four distinct error states, print sizing and tiling math measured directly against a real generated PDF, and saved data), and visually confirmed on desktop Safari and Firefox, including a real font-overflow bug caught with realistic long-content testing and fixed. Not yet verified on a physical iOS or Android device — if you're on mobile, it's built with only standard, widely-supported web features, so it's very likely to work, but this hasn't been confirmed hands-on yet.*\u003c\/em\u003e\u003c\/p\u003e\u003ch3\u003eFAQ\u003c\/h3\u003e\u003cp\u003e\u003cstrong\u003eDoes my data get uploaded anywhere?\u003c\/strong\u003e\u003cbr\u003eNo — including the logo or seal image. This is a single HTML file with zero network requests. Every free certificate maker checked in this tool's own competitive research (Templated, Free Document Maker, CertFusion, and others) generates your PDF on their server, meaning what you type is sent to them even without an account. This tool never sends anything anywhere; it's all read and rendered directly in your browser.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use my own logo?\u003c\/strong\u003e\u003cbr\u003eYes, for both document types — click the logo\/seal uploader, choose a PNG, JPG, or WebP under 2MB, and it's embedded directly into the certificate or warranty card. If you don't upload one, the Classic certificate style shows a drawn gold seal automatically; the Modern style and warranty card simply show no logo area.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eDoes this work offline?\u003c\/strong\u003e\u003cbr\u003eYes, fully. Once the file is downloaded, no internet connection is needed for anything — filling in the form, live preview, logo upload, or printing.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eWhat happens to my file if I lose the download?\u003c\/strong\u003e\u003cbr\u003eYour draft — document type, style, all text fields, and the logo — stays saved in this browser on this device, so you can reopen the tool and print again anytime without re-entering anything. The printed document itself isn't stored anywhere by the tool; once you print or save it, treat it like any other document you care about.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eCan I use this for client or commercial work?\u003c\/strong\u003e\u003cbr\u003eYes. Every certificate or warranty card you generate is entirely yours — no attribution required, no restriction on commercial, client-facing, or business use.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eIs there a subscription?\u003c\/strong\u003e\u003cbr\u003eNo. This is a one-time purchase of a single, self-contained HTML file. No recurring charges, no per-certificate fee, no limit on how many documents you print.\u003c\/p\u003e","brand":"My Store","offers":[{"title":"Default Title","offer_id":54670918811985,"sku":null,"price":5.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/files\/01-hero_7fe0f94a-e3f1-4938-a23d-4ee9d4990594.png?v=1787609922"}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1073\/4226\/6705\/collections\/01-hero_7fe0f94a-e3f1-4938-a23d-4ee9d4990594.png?v=1787659715","url":"https:\/\/untracked.tools\/collections\/business-admin.oembed","provider":"Untracked Software","version":"1.0","type":"link"}