Manifesto
The problem#
Financial software has the highest stakes for design and the lowest average quality. Teams optimize for correctness, a table satisfies correctness, and the rest gets bolted on: a chart library, a card, a modal. It works. It feels like nothing.
Generic component kits also fail the first financial requirement you hit:
- 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, so for half a second the screen shows a number that was never in the books.
The accounting model is missing too. Generic kits have no concept of a debit, a period that can be closed, an entry that must be reversed instead of deleted, an approval bound to a version, or a balance backed by evidence. Those things are the data model. Take them away and you have a spreadsheet with permissions.
Money has its own typography and conventions about four hundred years older than the web. Almost no component library follows them, and Lopifi does.
The thesis#
In a category where everyone's software is functionally adequate, taste is the differentiator.
The line is Emil Kowalski's, and Lopifi bets on it. When two accounting products compute the same right number, people pick the one that feels considered, because how a product feels is the only evidence of care a user can see. In finance they read that care as trustworthiness, and trust is what they're paying for.
Principles#
1. Unseen details compound#
Nobody consciously notices that the parentheses around a negative are case-shifted to sit with lining figures. They notice that the statement looks right.
1b. The ledger is the model, not a detail#
Double-entry, normal balances, period states and immutability hold the whole thing up. Collapse a debit and a credit into one signed amount and you've removed the control that lets anyone check the number. When design and the accounting model conflict, the model wins.
2. The numbers are the interface#
The card, the shadow and the radius exist to frame a figure. When chrome competes with the legibility of a number, the number wins.
3. Restraint is the aesthetic#
One accent per view. No gradients, no glow, no purple, no decorative motion on a data surface. A finance screen earns confidence by looking calm, and you get calm by taking things out.
4. Motion must justify itself#
Every animation has to answer "why does this move?" with one of five reasons: spatial consistency, state indication, explanation, feedback, or avoiding a jarring change. "It looks cool" isn't on the list. Frequency decides the rest. Something seen 200 times a day gets no animation. Something seen twice a month can have a little delight.
5. The layout is a grid, not a vibe#
8px all the way down, in four deliberate layers, and nobody eyeballs spacing. A new component drops into a structure that already exists.
6. Two typefaces, three sizes, three weights#
Hierarchy comes from contrast within a small set. A component that needs a fourth size should be two components.
7. Density is a first-class responsive dimension#
Most systems reflow. Finance UI has to re-rank: decide which of eleven columns matter on a 390px screen and design that view, instead of letting the table scroll sideways.
8. Own the code#
You copy the source into your repo instead of installing a dependency. A finance team will need to change the categorization rules, the fiscal calendar and the rounding policy, and you can't do that inside a black-box npm package. shadcn got this 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 isn't 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 and "use client" where interaction needs it. We don't contort for purity. |
Naming#
Lopifi: one word, short, easy to say and type. The registry namespace is @lopifi, so installs read as sentences:
npx shadcn@latest add @lopifi/profit-and-loss
We picked memorable over searchable. react-finance-ui would rank better and be forgotten sooner.
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 behind the audit pass. Encoded indocs/craft/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 lists what we turned down and why. - Refactoring UI: grayscale-first, constrained scales, shadow as elevation instead of decoration.
- Mercury, Ramp, Stripe, Linear, Wise, Monzo: read closely in
docs/moodboard.md, borrowed from selectively. - Ramp, Mercury, Brex, Slash, Rho, Bill, Wise, Stripe: the spend and banking layer, read closely in
docs/product-teardowns.md. - Numeric, FloQast, Puzzle, Digits, Campfire, Xero, NetSuite: the accounting layer, same document. Together 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, double-entry itself. We didn't invent any of it.