The gap between "it works" and "it feels right"
About small decisions that slowly shape how a product feels.
At some point, every product reaches a familiar state.
Everything works. Nothing is broken.
And yet, something feels off.
Buttons respond, pages load, data flows from backend to frontend and back again.
From a purely technical perspective, the job is done.
But when you actually use the product, it feels heavy. Slightly awkward. A bit exhausting to interact with.
This is the gap between "it works" and "it feels right".
Most teams are very good at shipping things that work.
That is already hard, and it deserves respect.
But "working" is only the baseline. Users do not experience code paths, they experience friction.
The tricky part is that this gap rarely shows up in specs or tickets.
There is no task called "make it feel calm" or "remove tiny annoyances".
Instead, it hides in details that are easy to dismiss:
- A layout that jumps when content loads.
- A button that technically works, but reacts a fraction too late.
- A form that validates correctly, but makes you feel like you are doing something wrong.
None of these demonstrate incompetence. They usually come from reasonable decisions made under time pressure.
Frontend lives right at the intersection of logic and perception.
The browser will happily execute almost anything you give it.
Users are less forgiving.
I see this gap most often when projects are built feature by feature, without stepping back to look at the whole flow.
Each piece is correct in isolation, but together they create noise:
- Animations compete for attention instead of guiding it.
- Components solve local problems, but break rhythm at the page level.
- State management technically works, but causes subtle lag.
The product works, but it does not breathe.
Closing this gap is rarely about adding more.
It is almost always about removing, simplifying, or aligning things that drifted apart over time.
This is where frontend decisions stop being about frameworks and start being about restraint.
- Do we really need this animation, or does it just exist because we can do it?
- Should this interaction be instant, or should it acknowledge the action first?
- Is this abstraction helping, or just making the mental model harder to follow?
None of this is glamorous work.
It does not show up well in demos.
But it is what separates products people tolerate from products people enjoy using.
From a technical side, this often means boring choices:
- Predictable layouts.
- Fewer dependencies.
- Clear data flow.
- Stable component contracts.
- Performance budgets that are actually respected.
From a human side, it means caring about how things feel when no one is watching, when the product is used daily, not presented.
The gap between "it works" and "it feels right" never fully disappears.
Products evolve, requirements change, tradeoffs pile up.
But being aware of it changes how you build.
You stop asking "does this work?"
You start asking "does this make sense for the person using it?"
That question does not have a single correct answer.
But asking it consistently is what keeps the gap from turning into a canyon.