Knowing what to build

Read the anatomy section of Emil Kowalski’s writeup of Vaul, his drawer component, and the striking part isn’t the implementation. It’s the length of the list. The number of separate decisions someone had to notice were decisions at all: what the drawer does when you flick it versus drag it slowly, what happens to the page behind it, where the scroll goes, what a velocity threshold should be before it counts as a dismissal.

Any competent engineer can implement each of those once they are written down. Almost nobody produces the list. That gap is the whole thing, and it is not a coding-ability gap.

The list is the hard part

We talk about engineering skill as though it were mostly execution, because execution is the part that is legible: it compiles or it doesn’t, the test passes or it fails, the review approves or it requests changes. Noticing has no artifact. There is no diff for the bug you didn’t ship because you thought about the empty state before you built the populated one.

So the trained eye reads as taste, which makes it sound innate and unteachable. It isn’t. It is the accumulated residue of having been wrong in public, plus the habit of reading other people’s work closely enough to see the decisions rather than the output. The reason Emil’s article is worth more than its code is that it externalises the noticing, which is normally the invisible half.

One line on this site

The index has a line under the contribution graph saying when I last shipped. Writing it is trivial: take the newest day with activity, subtract it from today, print “today” or “3 days ago”. The decision that took real thought was this one:

const MAX_AGE_DAYS = 14;

export function shippedLabel(date: string, now: Date): string | null {
  const days = differenceInCalendarDays(now, parseISO(date));

  if (days < 0 || days > MAX_AGE_DAYS) {
    return null;
  }
  …
}

Past a fortnight the line renders nothing at all. That is the entire feature, and nothing about a “last shipped” label demands it. You only get there by asking what this looks like on a bad month, and then noticing that “last shipped 5 months ago” is worse than no line, because it is not broken. It is a confident, precise report on an absence, sitting directly under a graph the reader is already scanning for signs of life.

The same question, asked one step earlier, chose the data source. The obvious one is GitHub’s public events feed, which carries pushes to the second. Most of my work is in private repositories, so that feed is empty and the newest public push is months old: precision, pointed at the wrong number. The contributions API counts private contributions and only resolves to a day, which is less precise and true, and the line never claims to know more than the day.

Same class of decision, one file over: the paragraph about photos and the collage that follows it. The covers of three books assert taste and evidence none of it. A sentence about why those three is a claim someone can disagree with. The images were never the problem; shipping them without the sentence was.

How to get the list

The mechanical version of “have taste” that actually works for me is to ask three questions of anything before building it. What does this look like empty, and is empty the common case? What does it look like when it goes wrong, and does the failure explain itself? What does it look like in six months if nobody touches it?

None of those are about code, and all three produce work. That is the point. The engineering was never the constraint; the constraint is that most requirements documents describe the happy path of a system on the day it launches, and everything interesting happens outside that description.