All posts
May 6, 2026 · 5 min read

Patching NPM packages for custom needs

Have you ever had a situation where some NPM package doesn't quite fit your needs, but you don't want to fork it or wait for a PR to be merged? There is a simple solution.


Most internal tools feel like they were designed to be correct, not to be pleasant. They work, technically. But opening them is a small act of resignation.

I’ve spent the last few years building developer-facing tools — dashboards, CLIs, admin panels — and I keep returning to the same question: what makes a tool feel like something you want to use versus something you have to use?

The answer isn’t dramatic. It’s a handful of small commitments, made consistently.

Typography isn’t decoration

The first thing I got wrong, early on, was treating typography as styling. Something you deal with at the end, after the “real” work is done.

But in a tool — something dense with text, data, labels, actions — typography is the design. When the type is wrong, nothing else can save it.

A few things that compound quickly:

  • Size hierarchy. If everything is the same size, nothing has weight. A clear scale (11px labels, 14px body, 18px headings) creates structure before the user reads a word.
  • Line height. Data tables want tight lines (~1.3). Paragraphs want room (~1.65). Mixing them without intention looks lazy.
  • Letter spacing. Small uppercase labels at +0.06em feel considered. The same labels at 0em feel heavy.

None of this is magic. It’s just noticing what’s actually on the screen.

Density signals intent

There’s a concept I think about a lot: density as communication.

A very sparse UI — lots of whitespace, one thing per screen — signals “this is simple.” Sometimes that’s right. But in a tool where the user is doing real work, sparseness can feel condescending. It hides complexity rather than managing it.

Conversely, a very dense UI says “this is powerful, but you’ll need to learn it.” Most internal tools tip too far this way by default — not out of intention, but because nobody went back to clean things up.

The sweet spot is something like: show the user what they need, grouped sensibly, with clear affordances. Not gamified, not spartan. Professional.

Every action needs a response

Feedback is a conversation. When a user clicks something, they’re asking a question: did that work?

Tools that go silent after an action — no loading state, no confirmation, no change — force users to wonder. That wondering is cognitive friction. It slows people down and, worse, erodes trust.

Simple things go a long way:

  • A button that disables and shows a spinner on submit
  • A row that highlights briefly after an update
  • An error message that names the problem, not just the status code

You don’t need animation for this. Just responsiveness.

The compound effect

None of these things is impressive alone. A good font, reasonable density, honest feedback — nobody writes a blog post about your loading state.

But they compound. Together, they produce an experience that feels cared for. And that feeling — hard to name, easy to notice when it’s absent — is what separates a tool people recommend from one they quietly resent.

The most frequent compliment I get on shipped tools isn’t about features. It’s some version of: “it doesn’t feel like a work tool.”

That’s the goal.