Quip: making an invisible action tell the truth.
Quip finds a GIF and copies it in a second. The screen never shows the copy happen, so the design has to prove it did.
The two GIF tools I relied on stopped being updated.
Finding a GIF and getting it into a chat is a small job. Two apps used to do it, and both were abandoned.
Finding the right GIF and dropping it into a message is a small, everyday thing. For a while two tools did it well enough: InaGif, and GIPHY’s own macOS app. Both stopped being maintained. They still launched, but nobody was fixing them.
So I built Quip, a menu-bar app that searches Giphy and copies a GIF to the clipboard in a click. The people who came to test it were mostly refugees from those two dead tools. They found it through a post I wrote on Reddit and on GitHub, and they arrived with years of habits and firm opinions about how a GIF picker should behave. That turned out to matter far more than anything I could have guessed at on my own.
The app’s main action leaves no trace on screen.
Copying to the clipboard is invisible. Nothing moves and nothing confirms, so there is no way to be sure the click landed.
Quip’s whole reason to exist is one move: find a GIF, copy it, paste it somewhere else. That move is invisible. When a copy succeeds, nothing on screen changes. The clipboard is a silent place, and the popover gets out of the way the instant a result is clicked.
This is the interaction the app repeats more than any other, and at first it offered no feedback at all. People clicked, saw nothing, and clicked again, unsure whether to switch apps and paste or keep trying. An app whose main action leaves no trace has to earn trust some other way. The rest of the work was giving that unseen click an answer.
I built Quip to fix my own annoyance, then let real use redesign it.
Solo, start to finish: the design, the Swift, and the release pipeline are mine. The sharpest fixes came from watching other people struggle with it.
Quip is mine end to end. I designed the interaction, built it in Swift and SwiftUI, and set up the pipeline that signs and notarizes each release before it ships. It is a personal project, open source, with no one else on it.
What I did not do alone was find the problems. Across two weeks and 16 releases, a dozen or so people put Quip to use and told me where it broke: comments on Reddit, direct messages, and a few sessions where I sat and watched someone use it. Nearly every fix in here began as a person getting stuck in front of me, or a message that opened with is it supposed to.
The move it makes most often had to say whether it worked.
A copy that succeeds shows a mark. More important, a copy that fails now says so, instead of claiming a success it never earned.
The first fix was the obvious one. When a copy lands, the thumbnail shows a brief “Copied” mark. The click has an answer.
The harder problem was failure. Early on, when a GIF failed to download, the app still showed “Copied”. People switched to their chat, pasted, and got nothing, or a broken file. Then they blamed themselves, or the chat app, because Quip had just told them the copy worked. A cheerful confirmation that lies is worse than no confirmation at all, because it sends someone away confident and wrong. The fix tied the mark to the real result, so a copy that fails now says the copy failed.
One failure used to take the whole window with it. A single GIF that would not copy replaced the entire popover with a full-window error, wiping out the grid the person was browsing over one small hiccup. Now the failure stays where it happened: a quiet “could not copy” mark on that one tile, and everything else holds its place.
Dragging a GIF into a collection had to actually file it.
Collections let a favourite go into a named bucket. The gesture looked right long before it worked, which is its own kind of lie.
Collections are named buckets for the GIFs worth keeping. The first way to file one was a right-click menu: right-click, Add to Collection, choose from a submenu. People found it slow and hard to discover, and a menu is the wrong mental model for putting a thing into a bucket. So filing became direct: drag the GIF onto the collection’s chip.
Then came the sharpest failure in the app’s short history. For one release, the drag behaved exactly as it looked. A GIF could be picked up, dragged onto a chip, and dropped as the chip lit up. It looked filed. It was not. The GIF was never added, and nothing said so, so people believed they had organized their favourites when they had not. A gesture that lies while looking like it worked gives no signal to try again. An error would have; this gave nothing. The cause was a wrong assumption about how macOS carries a dragged item; the fix routed the drag through a shared context so the drop does what the animation promised.
There was one more gap. The chips lived above the favourites, out of reach during a search, and the moment a person most wants to file a GIF is the moment they have just found it. So the chips moved into a drawer that stays in reach and slides into the search view the instant a drag begins. And because filing changes nothing in the grid, filing is invisible too. It needed the same honest signal the copy mark gave, one layer up: a brief “Added to” toast, so the drop has an answer.
- right-click submenuslow, hard to find
-
drag onto a chipdirect manipulation
gif favourites
-
filing drawerfollows into search
favourites work reactionsadded to work
A tool summoned for two seconds must never interrupt.
Quip is anti-modal by design. It interrupts once, on first launch, and never again.
Quip is the kind of tool a person calls up for two seconds and dismisses. So it holds a firm rule: it does not interrupt. When it finds an update in the background, it does not throw a window that steals focus mid-task. It marks its menu-bar icon with a small dot and offers Install Update in the right-click menu, and that is all.
The rule has one deliberate exception. Quip keeps no Dock icon and opens no window when it launches, so a brand-new user could install it, open it, and see nothing but a small icon they might not notice. So on the very first launch, and only then, the popover opens itself once, anchored to its menu-bar home, to point at where the app lives. That one interruption exists to help a new user find the app. It breaks the no-interrupt rule to serve the reason the rule is there.
The loop was short, and it closed on the failures that mattered.
16 releases in 11 days, most shipping a fix the same or next day. The trust bugs were found in use and closed.
Quip shipped 16 times in 11 days, from 1.0.0 to 1.1.14. Because it updates itself, a fix reached people the same day it was written; the release history shows clusters of versions on the same and neighbouring days, each one answering something someone had just run into. The “Copied” that lied and the drag that filed nothing were both found this way, in ordinary use, and both were closed.
None of this is a large study, and the numbers stay small and honest: a dozen or so testers, two weeks, one person building. Still, the app is notarized, signs and updates itself, keeps its API key in the macOS Keychain, and the people who came over from the two dead tools stayed on it. For something that lives in the corner of the screen, that is enough.
I should have tested the failures before shipping the successes.
Both trust bugs shipped before use caught them. They are also where the whole idea came from.
The two failures I am least proud of, the confirmation that lied and the drag that only pretended to file, both shipped. I had tested that copying worked and that filing worked. I had not tested what either one does when it fails, and failure is exactly where a hidden action does its damage, because there is nothing on screen to contradict it. If I built this again, the first thing I would test on any action that changes nothing on screen is what it says when it goes wrong.
It is also fair to admit that the conviction running through this whole project, that a silent failure is the worst kind, is not something I brought to it. I shipped the silent failures myself, watched them cost people their trust, and learned it the slow way.
A few of these lessons outlast the GIF app.
The specific fixes were about GIFs. The habits underneath them are not.
Quip’s problems turned out to be versions of a few larger ones, and those are the parts worth keeping.
- An invisible action needs a visible, honest answer. Copy and file both change nothing on screen, and both needed a signal that tells the truth when the action fails, since success was never the hard case.
- A silent no-op is the worst failure there is. The drag that looked filed but was not did more damage than any error message would have.
- Direct manipulation beats a menu for putting a thing somewhere. Dragging a GIF onto a chip was the single biggest gain in collections, once it actually worked.
- The chrome must not fight the content. Scroll bars kept covering the stars and GIFs people were reaching for, and the answer was to remove the chrome rather than tune it. A half-shown row at the edge now signals there is more below, doing the scroll bar’s job without sitting on top of the content.
- A control has to hold up on any background and in any theme. A whole group of Light-mode users once got dark text on a dark panel and could not use the app until it was fixed. The copy icon and the favourite star kept vanishing on bright thumbnails, too, until a darker outline let them read on anything.