Manifesto
The problem
Financial software is where design quality has the highest stakes and the lowest average. The reason is structural: fintech UI is usually built by teams optimizing for correctness, and correctness is satisfied by a table. So you get a table. Then a chart library gets bolted on, then a card, then a modal, and the result works and feels like nothing.
Meanwhile every generic component kit fails the first real financial requirement:
- It renders
-1234.5where an accountant expects(1,234.50). - It stores money in a float and loses a cent at scale.
- It centers a column of numbers, so no two decimal points align.
- It has no idea that JPY has zero decimals and KWD has three.
- It treats
nulland0as the same thing, which in finance is the difference between "we don't know" and "it's zero". - It animates a balance counting up, which is charming exactly once and misleading forever.
And past the numbers, the model itself is missing. Generic kits have no concept of a debit, a period that can be closed, an entry that must be reversed rather than deleted, an approval that binds to a version, or a balance that has to be supported by evidence. Those aren't features layered on top of a data model — they are the data model, and they're what makes accounting software different from a spreadsheet with permissions.
Lopifi exists because money has a typography, a grammar, and a set of conventions four hundred years older than the web, and almost no component library respects any of them.
The thesis
In a category where everyone's software is functionally adequate, taste is the differentiator.
That's Emil Kowalski's framing and it's the whole bet. If two accounting products both compute the right number, the one that feels considered wins — not because feel beats function, but because feel is the only remaining signal of care, and users read care as trustworthiness. In finance, perceived trustworthiness is the product.
Principles
1. Unseen details compound
Nobody will consciously notice that the parentheses around a negative number are case-shifted to align with lining figures. They will notice that the statement looks right. A thousand barely audible voices singing in tune.
1b. The ledger is the model, not a detail
Double-entry, normal balances, period states, and immutability are load-bearing. A component that renders a signed amount where an accountant expects a debit and a credit hasn't simplified anything — it has removed the control that makes the number checkable. Every design decision in this system defers to the accounting model when the two conflict.
2. The numbers are the interface
Everything else — the card, the shadow, the radius — exists to frame a figure. When a decision trades off between chrome and legibility of a number, the number wins. Every time.
3. Restraint is the aesthetic
One accent per view. No gradients. No glow. No purple. No decorative motion in a data surface. Financial confidence reads as quiet, and quiet is achieved by subtraction. The most expensive-looking interfaces are the ones that removed the most.
4. Motion must justify itself
Every animation answers "why does this move?" with one of: spatial consistency, state indication, explanation, feedback, or preventing a jarring change. "It looks cool" is not on the list. And frequency governs everything — a thing seen 200 times a day gets zero animation, a thing seen twice a month can have delight.
5. The layout is a grid, not a vibe
8px, all the way down, in four deliberate layers. Spacing is not eyeballed. This is what makes a system extensible: any new component drops into a structure that already exists.
6. Two typefaces, three sizes, three weights
Hierarchy comes from contrast within a small set, not from a large set. A component that needs a fourth size is a component that needs to be two components.
7. Density is a first-class responsive dimension
Most systems responsively reflow. Finance UI must responsively re-rank — decide which of eleven columns matter on a 390px screen, and design that view rather than letting it scroll sideways into uselessness.
8. Own the code
Copy-paste distribution, not a dependency. A finance team will need to change the categorization rules, the fiscal calendar, the rounding policy. A black-box npm package is the wrong shape for that. shadcn was right.
Non-goals
| Not doing | Why |
|---|---|
| A charting library | We wrap one (Recharts/visx). Charting is solved; money-aware axes and negative-aware baselines are not. |
| A data layer | No fetching, no cache, no ORM. Components take data and render it. |
| Every currency's cultural formatting | We use Intl correctly and expose escape hatches. We don't hand-roll locale tables. |
| A theme marketplace | One system, one point of view, two modes (light/dark) plus one accessibility variant. Taste is not a config option. |
| Crypto-maximalist visuals | Swap and FX components are included. Neon gradients and glow are not. |
| Server components as a constraint | Components are RSC-safe where possible, "use client" where interaction demands it. We don't contort for purity. |
Naming
Lopifi. One word, short, easy to say and to type. Registry namespace @lopifi, so installs read as sentences:
npx shadcn@latest add @lopifi/profit-and-loss
Naming creates identity; memorability beats discoverability. react-finance-ui would be more searchable and worse.
Alternates considered: Tender (good, ambiguous), Numeraire (precise, unpronounceable), Denom (crypto-coded), Tally (taken, and reads as counting rather than accounting).
Influences, credited
- Emil Kowalski — the animation decision framework, easing philosophy, the Sonner principles, interruptibility, the blur-masking trick. Encoded throughout
docs/motion/. ibelick/ui-skills— the baseline-ui constraint set, motion-performance rules, accessibility priority ladder, the DESIGN.md evidence discipline, and the three-proof gate that governs the audit pass. Encoded indocs/craft/03-quality-bar.mdandDESIGN.md.- The wider ui-skills registry — Core Web Vitals thresholds from
addyosmani/web-quality-skills, presence and icon-morphing discipline fromraphaelsalaja/skill, the Base UI migration path fromshadcn-ui/ui. Taken narrowly: most of that registry is out of stack or out of scope, and prior art names what we turned down and why. - Refactoring UI — grayscale-first, constrained scales, shadow as elevation not decoration.
- Mercury, Ramp, Stripe, Linear, Wise, Monzo — read closely in
docs/02-moodboard.md, taken from selectively. - Ramp, Mercury, Brex, Slash, Rho, Bill, Wise, Stripe — the spend and banking layer, read closely in
docs/04-product-teardowns.md. - Numeric, FloQast, Puzzle, Digits, Campfire, Xero, NetSuite — the accounting layer, same document. Between them they define the workflow we're designing for, and none of them has both the model and the interface.
- Four centuries of accountants — the rule lines, the parentheses, the em dash for nil, the double-entry itself. We didn't invent any of it. We just stopped ignoring it.