The Door That Was Never Open
I had a clean, evidence-backed negative result about my own product. It was meaningless, because it measured a door nobody could walk through.
Date
Category
Writer

For about a month I believed I had the beginnings of an answer about my own product, and the answer was bad.
I had built the thing. It was deployed. It was on my phone's home screen. And the data from my own use was unambiguous: nothing was happening.
What the log said
I read my own history carefully, and the care matters here. From a copy of browser storage, through a path that never booted the application so the reading itself would not be recorded as a visit, and without reading a single line of my own text. The copies were deleted afterwards.
Measure | Value | Reading |
|---|---|---|
Arrivals | 60 | Looks like use |
Lines left | 56 | Looks like capture |
Lines of 5 characters or fewer | 40 | Not capture. Typing tests |
Longest line | 20 characters | Nothing real was ever left |
Cat touches | 433 | 64% of all events |
Arrivals within a single minute | ~25 | Reloading a build |
Longest gap between arrivals, ever | 10.4 hours | Never went a day without opening it |
Table 1. The founder's own log. Every row is the signature of development, not use.
The last row is the one that settles it. A person using a product has gaps. Weekends. Busy days. A week where they forget. The longest gap in this product's entire history was ten hours, which is the shape of someone who works on it every day and checks it before bed.
So I recorded the honest conclusion: capture never happened, re-finding could not have happened, value cannot be assessed. Not a failure. An absence. You cannot falsify a hypothesis that was never tested.
And then the actual reason
The next round was supposed to be about product direction. It turned into something else, because I went to check a boring technical detail and found this:
The product had no web app manifest.
Three consequences, and each one is fatal on its own.
On Android
A web application must be installed before it can register as a share target. Chrome requires this. Without a manifest there is no installation, so there was no installation, so the product could not appear in the share sheet at all.
Not ranked low. Not hard to find. Absent.
On iOS
WebKit's Intelligent Tracking Prevention caps all script-writable storage at seven days of Safari use without user interaction on the site. John Wilander's post is explicit about the scope: IndexedDB, LocalStorage, Media keys, SessionStorage, and Service Worker registrations.
There is exactly one exemption, and it is the one I did not qualify for: "Web applications added to the home screen are not part of Safari and thus have their own counter of days of use."
So every world I created on my phone was being deleted by the browser after a week, silently, as designed, by a privacy mechanism working exactly as intended.
Together
The entire premise of the experiment, put it on your phone, drop real things in, come back later, was mechanically impossible on both platforms at once.
The experiment did not fail. It was never possible to run.
Why I had not noticed
Every round of work had been driven from a desktop. On a desktop the manifest is irrelevant: the site loads, storage persists, everything works. The product was fine in the only place anyone ever looked at it.
This is the real lesson and it is not about manifests. A missing manifest is a trivial bug. What is not trivial is that it produced a false negative about the product's value, which I then acted on, documented, and nearly made a strategic decision from.
The fix, which took an afternoon
Plus the icons, drawn by the program's own rendering code so they use the same palette as the product rather than being a separate asset that drifts. Plus the handful of meta tags iOS actually reads.
Verified live rather than assumed: bundle hash matching the local build, manifest served with the correct content type, both icons returning 200.
One deliberate restraint in the share adapter
Worth noting because it was tempting to do otherwise. The share adapter never writes.
A shared item arrives in the input, focused, and the person presses the button. It is not saved automatically.
The reason: any link of the form /?text=... would otherwise put a note into someone's world, recorded with provenance "observed" and actor "user", when the user typed nothing. A false record is worse than an extra tap. Provenance has to mean something or it means nothing, and one automatic write would poison it permanently.
The platform map, which I should have made a year earlier
Capability | Android | iOS |
|---|---|---|
Installable to home screen | Yes | Yes |
Survives storage eviction once installed | Yes | Yes, exempt from the 7-day cap |
Appears in the system share sheet | Yes, after install | Never, for a web app |
Share-sheet position controllable | No | No |
File sharing into the app | Needs POST and a worker | Not available |
Table 2. Platform capability map. The third row is permanent and cannot be designed around: on iOS only a native share extension can register there.
Making this table is a two-hour job. I did it in month eleven. Had I done it in month one, the entire share-target question would have been correctly scoped from the start, and I would not have spent a month drawing conclusions from a broken instrument.
The discipline I took from it
I had a clean, defensible, evidence-backed negative result. I had numbers. I had documented them carefully and written a considered analysis. And the result was meaningless, because it measured a door nobody could walk through.
So this now runs before any negative conclusion about anything:
Before concluding that people did not choose your product, prove they could have.
Not "the site loads." Not "it works on my machine." Specifically: at the moment of the behaviour you are hoping for, on the device where it would actually happen, was the path open? Was the icon there? Was the share-sheet entry there? Did the data survive the week?
Negative evidence is the most valuable kind and the easiest to fake, because absence looks identical whether the cause is rejection or inaccessibility. One of those tells you to change the product. The other tells you to check the plumbing.
They are indistinguishable in the log. They are not remotely the same thing.
Sources
Wilander, J. (2020). Full Third-Party Cookie Blocking and More. WebKit blog, 24 March 2020. webkit.org/blog/10218
Related reading
Latest Articles.
© Moc Mallen Studio
Thoughts, ideas, and perspectives on design, simplicity, and creative process.

