Wrapped
Feed it a file you exported yourself. Get something worth posting.
Live and free. Runs on your own machine.
What it does
Reads a WhatsApp chat export or a Google Calendar export, counts it in your own tab, and hands back a card or a video.
Two kinds of fuel, one product
A chat export becomes who texts first, who replies faster, the 2am hours, the longest silence. A calendar export becomes the bill: every standing meeting ranked by the person-hours it burned.
Counted, not guessed
Every number is counted in the page from the file you dropped. Six optional readings add an opinion on top, and each one has a Counted only button beside it.
A card or a video
Both rendered in the browser — no upload, no queue. The chat video runs up to 28 seconds, the calendar one 11 to 14.
How it got built
The problem
Two separate products, each one shipped: a chat-stats tool and a meeting-cost tool. Both worked. Both looked like a toy, because a single-trick site with one input and one output reads as a weekend project no matter how good the maths is.
The constraint that shaped it
The counting had to keep working with the model switched off. A tool whose only mode needs a network call is a tool that is broken during an outage and useless on a plane — and for a product whose whole promise is that your file stays with you, an AI-only path quietly makes the promise conditional.
Decisions
- Merge them, and take the traffic hit on one domain
Same product, different fuel. Two sites split the audience and made each half look smaller than it was. The old addresses now redirect in rather than competing.
- Every AI mode has a no-AI twin
Each reading has a Counted only button that touches no network. A test presses all of them in a window with no
fetchat all, so a mode cannot quietly become AI-only in a later change. - Pick the provider on its terms, not its price
The model runs through a chain of providers, ordered by what their terms permit rather than what they charge. A free tier that may train on the input would make the sentence on the page false, so it is not in the chain — and if the provider ever changes, the copy changes in the same commit.
Where it landed
Live, with the one honest exception named on the page: the counting never leaves your machine, and asking a model to read the chat does. The button says who receives it before it sends.
What it taught me
The promise had been written once and then quietly outgrown. When the reading feature shipped, four surfaces were still claiming nothing is ever uploaded — true when written, false by then. Chasing one sentence across every page it had spread to took longer than building the feature that broke it.
What I’d do next
A real rate limiter. The current one is per-instance and leaky by design, which is honest but not sufficient now that six modes and a question box exist.