Hamza Yerrou
Hamza Yerrou
Software Engineer
Index/Writing/Front-end craft
2026 · 04 · 18 · 9 min read

The craft of shipping is mostly the craft of stopping

Most front-end projects don't fail because of bad code. They fail because nobody knew when to call it done.

The last project I was brought in to rescue had been "almost done" for four months.

Four months of demos. Four months of this week we're fixing the typography, last week it was the chart colors, week before that it was the empty state illustration. The team was good. The code was actually solid. They were just stuck in a loop I recognise immediately now.

The polish trap

Once you can see the imperfections in something, you can't stop seeing them. That's the trap. A two-pixel alignment issue becomes a blocker. A hover transition that works fine starts feeling wrong. You spend an afternoon. Then a day. Then it's two weeks later and you've shipped nothing, and the thing you were polishing is being redesigned anyway.

The interfaces I'm proudest of are not the most polished ones I've built. They're the ones that shipped.

The problem is that front-end is uniquely exposed to this. A backend engineer can't see that the margin between a label and an input is 14px instead of 16px. You can. And once you see it, you can't unsee it.

Polish also feels safe. You can point at polished work and say "look how good this is." Shipping something that works but isn't beautiful takes a different kind of confidence — the confidence to say that working is enough, for now.

How I decide when to stop

I have two questions I ask before I call anything done.

"Would I be embarrassed if a potential client saw this right now?" If no, it ships. Not "am I proud of this." Just not embarrassed. There's a big gap between those bars and that gap is where projects go to die.

"If I disappeared tomorrow, could another engineer continue from here?" This one is more useful than it sounds. It forces you to name things properly, write the comment that explains a non-obvious constraint, extract the helper that makes the code readable. Those decisions compound over time. A slightly smoother animation does not.

Cut the thing

At iMedia24 we had a data visualisation component that got rewritten three times because the spec kept changing. After the third rewrite I asked a question we should have asked months earlier: what does a user actually decide differently because of this chart?

We couldn't answer it. We cut the component. No user ever asked where it went.

That should have been obvious earlier. But when you've spent weeks on something it becomes real in a way it never does to users.

The gap between "working" and "perfect" is where projects go to die.

The one habit that actually helps

Before touching any code, I write one sentence that starts with "this is done when..."

End of day I read it back. Did I hit everything in it? Yes: ship it. No: those specific things are what I'm still building.

Everything I noticed along the way that wasn't in that sentence goes on a separate list. That list almost always evaporates within a week. If something was truly important, it surfaces again. If it doesn't come back, it wasn't.

The "things I noticed later" list is not a backlog. It's a filter. Most items on it exist because you were tired at 4pm and everything felt wrong. Give them a week. Most disappear.

What this looks like in practice

Concrete version, because the abstract version is easy to agree with and hard to actually do:

  • Write "this is done when..." before you open your editor, not after
  • Keep a separate "later" list and never merge it with the current task
  • When you want to polish something, ask whether a user would make a different decision with the polished version
  • Ship to staging before you feel ready, because "feeling ready" is the polish trap rebranded
  • Say "done" out loud to another person and then move on

The first few times you ship something that isn't quite as polished as you'd like, it feels wrong. But the product works. Users see what's there, not what's missing. And what's there is enough.

← Older
Wallet UX in eight unforgivable mistakes