Hook
Purpose-built for planning and building products with AI agents.
More breakout videos from this creator.
You ask your agent to make your app feel polished, and it does. It also adds a purple gradient, because of course it does. Then you click a menu in Linear, and yours feels cheap. It works, nothing looks wrong, so why? So why does it feel cheap? I've shipped apps like that, built by an agent, and I couldn't have named a single reason. Emil Kowalski can name all of them. He's on Linear's web team, he made Sonner, the toast library people download about 48 million times a week, and he wrote his reasons down as skills your agent can read. So we tested them. One agent, one prompt: make this page feel polished. It did a good job. Then Emil's reviewer read the code, wrote that the work shows care, and blocked it with three notes. The first note is about the menu closing. Our agent made it leave on a curve that starts slow and speeds up, which is called ease-in. Freeze it 40 milliseconds after you click away. It has moved about a tenth of the way. Now the same menu, same 150 milliseconds, on Emil's curve: four fifths gone. Both finish at the same moment, and the left one feels slower, because it hangs right when you're looking at it. You clicked, your eyes went to the menu, and the menu sat there. Emil calls easing the most important part of any animation, and his rule fits in a breath: anything entering or leaving starts fast and settles. That's ease-out. Ease-in on an interface is banned. An agent can't feel 40 milliseconds. Emil says as much on his own site: AI can write animation code, and what it can't do is know what feels right. Most people call that taste, and treat it like something you're born with. Emil thinks almost every taste decision has a logical reason if you look close enough, so he teaches it. Two animations play side by side, you pick the one that feels better, and you write down why before he shows his answer. A reason you wrote down, an agent can follow. He even writes some of his posts for them: his table of durations came with a note, share them with your agents and tell them I said hi. So the skills are his reasons as rules with numbers. He even hands your agent his exact curve, so it never has to guess one. And his reviewer writes every problem the same way, as before, after and why. That's our first row. The second note is stranger. Close the dialog with Escape, and it plays its little exit animation. The reviewer wants that instant. Before any curve, Emil asks how often someone will see this. 100 times a day, like a command palette or a keyboard shortcut: no animation, ever. A fridge light that faded in would be cute exactly once. Tens of times a day, cut it way down. Dialogs and toasts that show up now and then get a normal one. The rare stuff, like onboarding or a celebration, is where delight goes. His example is Raycast: he opens it hundreds of times a day, it has no open animation, and he says that's the best version of it. And anything you start from the keyboard happens instantly, because you do it over and over, and every animation makes it feel slower. This summer shadcn asked why we're animating everything. Someone blamed Emil. shadcn pointed out that Emil's very first course covers when to animate, and the person who blamed him came back with, but we over exaggerated on our own. The third note was the gentle one. With reduced motion on, the agent switched every animation off. Emil wants fewer and gentler, so the fade stays and the movement goes. So what should the menu do when it does move? Try this one yourself. Two menus open on the same click. Pick the one that feels faster. Watch them once more. It's the right one, at 180 milliseconds, against 400 on the left, and Emil keeps everyday animations under 300. The rest has a number too. Never grow a menu from nothing, because nothing in the real world appears from nothing. Start it at 95 percent and invisible, like a balloon that still has a shape when it's empty. Grow it out of the button that opened it, since that's where it belongs. Spin a loading spinner faster, and the same weight feels shorter. Press a button and it shrinks to 97 percent the moment your finger lands. Each one, on its own, you'd never notice. Emil's line is that in the aggregate, unseen details become visible. Couldn't a linter do all this? Part of it. A linter can catch a menu growing from zero, or a transition on every property. It can't ask how many times a day someone opens your menu. And the rules bend. Sonner, Emil's own toast library, breaks two of them. Its toasts take 400 milliseconds, past his own ceiling, on plain ease instead of his curve. The skill says it's on purpose, the motion fits the vibe of the library, a bit slower and calmer, down to the name, which is French for to ring. A dashboard should feel crisp, a toast library can take its time. Every number in the skills is a default, and the reason next to it tells the agent when to break it, which is the part you can't put in a linter. You still have to ask for the right thing, and "make it bouncy" doesn't give an agent much. So one skill is a dictionary that works backwards. Describe the effect the way you'd describe it to a friend, like the bouncy thing when a popover opens, and it hands you the name: pop in. It has 91 of those. Stagger, items arriving one after another. Morph, one shape turning into another, like the Dynamic Island. Rubber-banding, the stretch you feel when you drag something the wrong way: drag a Sonner toast up and it slows down and eventually stops. And when the rules can't decide, the prototype skill builds several versions that look nothing alike, puts them behind a little picker, and you flip through them live. Four menus, four personalities, and you pick. Emil's line for it is that prototyping is thinking, and he posted a shorter version: invite friction to your work. The agent builds the options and the choice stays yours. Then the menu feels perfect on your MacBook. Emil's newest skill opens with a warning about that: the developer's MacBook is the least representative device the animation will ever run on. It hunts for why an animation drops frames on a phone, and it starts with his own library. 48 million downloads a week, and his line is: imagine Sonner at 30 frames a second, same easing, same durations, same code. Nobody would have cared. On a phone you also meet the problems a laptop hides. Tap a button and its hover color stays stuck. Tap into the search box and the page zooms in, because iPhone does that to text under 16 pixels, and the mobile skill fixes the size instead of turning zoom off. Then the break UI skill feeds the app its worst data, a menu item 90 characters long. No notes at all. Exactly one note, which is how you find out your app says "one notes". So did the skills fix our page? We gave the same agent the same prompt with Emil's skills installed. It used his curve in both directions. The menu opens in 180 milliseconds from 95 percent. The toast rises its full height from the bottom edge and leaves the same way. The dialog grows in place. Most of that you'd only catch in slow motion, which is the gap between good and great. Then we press Escape. The dialog played its exit. With every rule installed, the agent still animated the one key Emil says never to animate, and his reviewer would have blocked that one too. Open the first menu one more time, beside the new one, same click. Now you can name every reason it felt cheap. It left slow at the moment you were watching. It played an animation for a key you pressed. It went dead still for anyone who'd asked for less motion, when a fade would have done. Someone using your app couldn't tell you what changed, and they'd still pick the one on the right. Your agent has the reasons now, in a file. And that last row, Escape? The agent missed it twice. Now you can name every one. You'd have caught that one too.