Nobody Noticed, Because Everyone Was on a Desktop
Two claims were in my documents for months and both were false on a phone. A narrow window is not a phone: responsive layout is a claim about composition, never about input.
Date
Category
Writer

Two claims had been in my documents for months. Both stated confidently. Both repeated in several reports.
"It works offline."
"It accepts anything. Universal intake."
Both were false on a phone. Neither had been noticed, because every round of development had been driven from a desktop.
What the measurement showed
I finally drove the product on an emulated iPhone rather than a narrowed desktop window. Two findings, both fatal, both invisible from a laptop.
Nothing could get in
The only paths into the product were drag and paste. Touch has neither.
A finger never fires a dragstart event. HTML5 drag and drop simply does not exist on touch, as a matter of specification rather than implementation gap. And there is no paste gesture available to a web page in the way the product needed.
So on a phone, the entire capture surface of a product whose thesis is drop anything here was: typing text.
That is it. Not degraded. Not awkward. Absent.
And it did not open offline
There was no service worker, so the app shell was never cached, so with the network off the product did not load at all.
The data was local, which was the part I had been checking, and completely unreachable, which was the part I had not.
Why "responsive" hid it
This is the part worth dwelling on, because the failure is a design failure rather than an engineering one.
The layout was responsive. At phone width it reflowed correctly: no horizontal overflow, readable type, sensible spacing, tappable targets. It looked like a working mobile product in every screenshot anyone took.
Responsive layout is a claim about composition. It says the content arranges itself for the viewport. It makes no claim whatsoever about input, about whether the gestures your product depends on exist on that device.
And we test the first constantly and the second almost never, because the first is visible in a screenshot and the second is not.
A narrow window is not a phone. It is a desktop that has been made narrow, and it still has a pointer, a keyboard, a clipboard, and drag events.
Every mobile check I had run was in a narrowed browser. Every one passed. All of them were testing composition, and the failure was in input.
The assumptions I was swimming in
Writing them down afterwards was more uncomfortable than fixing the bug.
Assumption | True on desktop | True on touch | Load-bearing? |
|---|---|---|---|
A pointer exists and can hover | Yes | No | Yes. Half the affordances |
A keyboard is always present | Yes | No | Yes. Every shortcut |
The clipboard is reachable | Yes | Not by gesture | Yes. It was half of intake |
dragstart fires | Yes | Never | Yes. It was the other half |
The network is up | Usually | Often not | Yes. Nothing was cached |
The window is wide | Yes | No | No. This one I had handled |
Table 1. Five of six were load-bearing and unwritten. The one I had handled is the only one visible in a screenshot.
None of these were written down anywhere, because nobody writes down what has always been true. They were not decisions. They were the water.
The fixes, and what they cost
For intake: a + in the leave bar that opens the platform's own file picker and feeds the existing capture path. No new pipeline. The same code that handles a dropped file handles a picked one.
The fix is small precisely because the architecture underneath was sound. The product had a door and simply no handle on that side. That is worth noting as a positive result about the earlier work: a badly structured product would have needed a parallel mobile ingest path, and would probably still have one today.
For offline: a service worker that caches the shell network-first, and never caches the API paths. Network-first rather than cache-first, so a stale shell is never preferred over a live one.
Then a new gate, 21 assertions driven against the built site rather than a dev server, so that neither claim can quietly become false again.
The touch work underneath
Making things movable by finger was more interesting than expected, and the core problem is genuinely hard.
The ambiguity: a finger pressing a card and then moving might be starting a drag, or might be scrolling the page. You cannot know at touch-start, and you must not guess wrong, because guessing wrong either makes the page unscrollable or makes the cards immovable. Both are catastrophic and each is the natural failure of guessing the other way.
The resolution:
This is what every mature touch interface converged on, and rediscovering it from first principles made me appreciate why rather than merely copying it.
The second line matters as much as the first. Both hands share one function for computing where a drop would land. Not two implementations kept in agreement. Behaviour divergence between mouse and touch is almost always two code paths drifting apart over months, and the only reliable fix is to not have two.
The platform limits I could not design around
Two, stated because pretending otherwise would be the easy move.
iOS share-sheet capture is impossible for a web application. There is no web share target on iOS. Only a native share extension can register there. This is not a gap to work around, it is a capability that does not exist, and saying so is more useful than shipping something that approximates it badly.
Android file sharing needs a POST multipart target intercepted by a service worker. That is cheap now that a worker exists, but it changes the GET path that currently works, so it is classified as unknown and deliberately not built. A working simple thing is worth more than a possibly-working better thing until the better thing is actually required.
The operating change
The lesson is not "test on mobile." Everyone says that and everyone believes they already do.
The precise version:
The device you develop on is a set of assumptions you cannot see.
Not because you are careless. Because those assumptions are the medium you are working in. A pointer that hovers. A keyboard always present. A clipboard reachable by shortcut. Drag events that fire. A network that is up.
The only method I have found that surfaces them is to run the real product, on the real class of device, doing the real task, and to treat any claim that has never been checked there as unverified rather than true.
Two claims, months old, in several reports. Both false. The cost of finding out was one afternoon on an emulated phone, and the cost of not finding out was every conclusion I drew in between.
Related reading
Latest Articles.
© Moc Mallen Studio
Thoughts, ideas, and perspectives on design, simplicity, and creative process.

