Build on top, not over.
You depend on a small library. It prints how long ago something happened. Your product has a narrow column, and the long form does not fit.
timeago("2026-08-26") → "3 days ago" you need → "3d"
You could fork it and change the one line this afternoon. Or you could send the change upstream and wait.
Which?
Done.
- return n + " " + unit + (n === 1 ? "" : "s") + " ago"; + return n + unit[0];
Twenty minutes. It prints 3d. No review, no waiting on someone in a timezone you keep forgetting. It does exactly what you meant.
Upstream keeps moving.
Catching up is now a bigger job than the fork ever was.
Meanwhile, someone else hit your problem. They forked too. And someone after them. The one real problem is still unsolved for everyone who will hit it next.
A fork does not remove the maintenance. It moves it onto you and hides it in a place where nobody is counting.
You open an issue. Nothing happens for two days.
Someone who has held this for eight years asks why.
They answer within the hour. Three of their users rely on the long form in screen readers. The short form should be an option, not a change. You had not thought of that.
+ timeago(date, { short: true }) → "3d" timeago(date) → "3 days ago"
You add the option, and a test for it. Three weeks pass.
Waiting.
Still working after you stopped paying attention to it.
That friction was not overhead. That friction was the product. What you got was not your feature. It was your feature with the maintainer's knowledge compiled into it, carried forward by people who are not you, in releases you do not have to cut.
The page you are reading stands on this.
The further down you go, the more load a layer carries and the fewer people can name it. Deep layers are the ones nobody is thanked for. Building on top is how you pay into them, whether or not you meant to.
Next time, work the ladder down. Stop at the first rung that holds.
Read it properly. The behaviour you want is often already there, behind a flag, a hook, or a paragraph nobody scrolled to.
Ask in the open. An issue costs ten minutes and frequently returns a maintainer explaining why your approach breaks in a case you had not imagined.
Extend from outside. A plugin, an adapter, a wrapper. If the project gives you a seam, use the seam.
Send the patch upstream. Small, tested, one idea at a time, written so that someone who has never met you can say yes without a meeting.
Carry a local patch, in the open. If upstream is slow, run your change as a visible diff on top, keep the pull request open, rebase it.
Fork, and say why. Sometimes the direction genuinely diverges, or the project is abandoned, or its governance failed. Then fork honestly: publish the reason, credit the lineage, and take on the maintenance out loud.
In December 2014, io.js forked Node.js over how the project was governed. Nine months later it merged back, and Node 4 was the two of them together. In 2010, LibreOffice forked OpenOffice.org after its owner changed; the fork became the project. Both were rung six, done out loud.
Build on top, not over.