본문으로 건너뛰기
Chandler Nguyen
AI6분 읽기

I Built an App With Almost No UI. That Was the Point.

The best review of my comedy app came from a table with four friends and a round of drinks — and my first version failed it. So I removed the joke format, then I removed the interface. Here is what a one-gesture app forces, why a 75-second ceiling is a table-length constraint, and the uncomfortable part for anyone whose day job is attention metrics.

The best review of my comedy app came from a table with four friends and a round of drinks.

Somebody said "tell us a joke." I did what everyone does now: picked up my phone, opened something, and started scrolling with my thumb while five conversations waited for me to come back. That is exactly the behaviour I built Knora to avoid, and my first version failed the same test in the same way.

Knora is a free iPhone app. You shake the phone, a short comedy bit plays end to end in one or two voices, and then there is nothing else to look at. No feed to scroll, no library to browse, no account to create. The whole interface is a gesture. It is rated 18+ for language and subject matter, which is the point of the thing and also the reason it is not for everyone at the table.

I got there by removing two things, and neither removal was comfortable. The first one deleted a format users already understood. The second deleted most of the app.

The first thing I removed was the joke format

Knora started as a knock-knock joke app. It worked, in the sense that it produced knock-knock jokes on demand. The problem was that the form was the ceiling. Every knock-knock joke has the same skeleton — the setup, the "who's there", the reveal — and a model can write a good one inside that skeleton and still only ever produce a knock-knock joke. The structure decided how funny the app could be, and no amount of prompt work was going to beat the structure.

So I deleted the format. That meant deleting the thing people recognised, which is a strange thing to do to a product that had just started working.

What replaced it was a set of comic methods instead of a template. Each bit is built from exactly one method, never a mush of several: a real absurd rule applied to something tiny, or a story that takes its time and then turns, or something that opens like a compliment and isn't. Four are live. The generator picks one per bit; the app never chooses.

That single change did more for the output than every prompt revision before it. Which is the first uncomfortable lesson: sometimes the model was never the bottleneck. The container was.

The second thing I removed was the interface

Removing the screens was harder, because screens are how you show users you have built something.

An app opened at a table competes with the table. Every element I added — a browsable list of voices, a library of bits you liked, a little profile — made the phone more interesting than the people holding the drinks. The brief stopped being "make a good comedy app" and became "one gesture, then the phone goes back down."

So there is no onboarding and no sign-in. You can pick a voice and a language if you care, and otherwise a random teller is drawn on first launch and you never open the settings screen at all. There is no personalisation to tune, which means there is no personalisation to get wrong.

A voice-only comedy app with no microphone takes some explaining, so plainly: it never listens. There is nothing to say out loud and nothing to type. The bit is written on a server and sent to the phone as audio; the phone is a speaker with a shake detector attached.

What "no UI" actually forces

Removing the interface is not a taste decision. It is a set of engineering constraints wearing a design hat.

Every shake has to be instant. If a bit takes six seconds to appear, the table has already moved on and the phone is face down again. So bits are written and voiced ahead of time and served from a catalog. Live generation exists, but as the fallback and the refill — the thing that keeps the catalog from going stale, not the path a user waits on.

No browsing means no choosing. With no list to pick from, the app sends no style and no model choice. The backend draws one method, writes several drafts, and keeps the best one before any audio is made. The judgement moved to the server because there was nowhere on the screen to put it.

One bit is bounded to about seventy-five seconds. That is not a technical limit; it is a table-length budget. Long enough to tell a story, short enough that nobody at the table is waiting through the third minute of something that is not working.

The client is 2.5 MB. Almost nothing is in the app, because almost nothing should be in the app.

The writer is swappable. Production runs Gemini 3.8 Flash, with a different model doing the moderation and the best-of-N pick. Changing the writer is a config change and no app release at all, which matters when the model you are using gets replaced every few months.

You cannot automate taste

The most useful thing I learned is about evaluation, and it generalises well beyond comedy.

Four separate times, the automated judges scored output highly that my own ear called unfunny. Four times. A model can tell you whether the structure is intact, whether the method is recognisable, whether the turn arrives in the right place. It cannot tell you whether the turn lands. I kept trying to make it, and it kept agreeing with itself.

So I split the problem in two. Mechanical checks guard the things that can be checked mechanically: fabricated figures, recited source text, a leaked stage direction in the middle of a line, anything that punches down at a group, a body, an illness or a bereavement. The ear decides everything else, and I stopped trying to delegate it.

If you ship AI features, that split is most of the job. Find the part of quality that is genuinely verifiable and automate it without apology. Then be honest — to yourself and to whoever asks — that the rest is judgement, and that no amount of rubric will make it not be.

The README of this project says it plainly, and I have not found a better phrasing: never trust an automated pass on the comedy.

What I gave up on purpose

Two decisions that look like gaps, and one that is.

I cannot see how the app is used. No analytics SDK, no account, nothing collected. The privacy claim is real, and so is the cost: I do not know which bits land, which voices get skipped, or how many people open it twice. I find out when somebody tells me.

There is no share button. This is a bet, and I might have it wrong. Sharing is how a comedy app normally spreads, and I have deliberately not built the mechanism. The bet is that the phone gets passed around the table rather than the link getting passed around a group chat. If that turns out to be wrong, the fix is obvious and probably overdue.

There are no ratings yet. It is new. That one is not a design choice, it is just a lack of people.

The uncomfortable part if you work in media

My day job is media operations. The number I have spent a career optimising is attention: time on site, session length, return frequency. Knora's success condition is that you stop using it. About forty seconds, one laugh, phone down, back to your friends.

Measured the way I measure media, that looks like a failing product. It has no session depth, no retention loop, no reason to come back tomorrow. It has one reason to come back at all, which is that the last one was funny.

I do not think that makes it a better product than the ones chasing attention. It does make it a useful reminder that "more engagement" is a choice about what you are building, not a law of nature. And it is much easier to make that choice in a side project that nobody is paying for.

If you have built something whose best outcome is a shorter session, I would genuinely like to hear how you reasoned about it — that is not a design space I get to spend much time in during the day.

The app is free on the App Store, and the notes on the design are here. If you try it and a bit does not land, tell me. The whole app is the joke.

Cheers, Chandler