Skip to content

Roadmap

Build order is deliberate. Each milestone proves something the next depends on.


M0 — Foundations (docs complete, tokens shipped)

Deliverable: @lopifi/theme installable, and every claim in the design docs demonstrable.

  • tokens.css — the complete set from foundations/, both themes, plus the signal palette
  • Tailwind v4 @theme + v3 preset
  • scripts/check-tokens.ts — contrast ratios computed from tokens, grid conformance on every spacing value, failing the build on violation
  • Font subsetting + size-adjust fallback metrics, CLS measured at zero
  • Docs site skeleton with theme / density / signal / reduced-motion toggles

Exit gate: a contrast-failing token change fails CI.


M1 — The money proof

Deliverable: correctness, provable. The thing that makes this a finance library.

  • lib/money.types.ts, format-money.ts, allocate.ts, fiscal-period.ts
  • Money · Delta · Figure · Percent · Rule
  • Property-based tests (fast-check): format(parse(x)) === x over all valid inputs; allocate(total, w).sum() === total over all inputs
  • Every currency edge case: JPY 0dp, KWD 3dp, bigint, negative zero
  • tnum + case verified visually — a rendered column of mixed-sign values with proven decimal alignment
  • The greyscale test automated as a visual-regression assertion

Exit gate: a public "Why most money components are wrong" doc page, with live side-by-side comparisons. This is the marketing artifact and it writes itself if M1 is done properly.

Why first: every component above this inherits its correctness. And the case/paren-alignment craft is the hardest thing to retrofit.


M2 — Surfaces

  • Card base · BalanceCard · KpiCard · StatCard · KpiRow
  • Sparkline · Trend · StatusPill · AsOf · Redacted · Reference · EntityMark
  • EmptyState (3 variants) · ErrorState · Skeleton · StaleIndicator
  • The isometric object library + the first five scenario illustrations
  • Elevation, borders, and dark-mode top-highlight validated across every surface

Exit gate: a dashboard built entirely from these that looks finished, at 390px and 1280px.


M3 — The table

Deliverable: the workhorse, at every width.

  • TransactionTable · TransactionRow · TransactionCard · TransactionDetail
  • Virtualization with correct aria-rowcount/aria-rowindex
  • Full grid keyboard model — arrows navigate, one tab stop
  • All four responsive presentations, including the 768–1024 sticky-both-edges pattern
  • FilterBar (URL-backed) · BulkActionBar · ColumnManager · ExportMenu
  • use-density + DensityToggle

Exit gate: 10,000 rows at 60fps and INP under 200ms on a mid-range Android at 4× CPU throttle; full keyboard-only operation; the 390px card list is genuinely usable, not a compromise.


M3.5 — The ledger core

Deliverable: the general ledger the statements are a view over. Built before the statements, because a statement that can't drill down to journal entries is a picture of a statement.

  • JournalEntry · JournalEntryForm · JournalEntryTable — two columns, always
  • AccountPicker · ChartOfAccounts · AccountRegister · DimensionPicker
  • AdjustingEntryForm with auto-reverse defaulting on for accruals
  • EntryReversalDialog — and no delete path anywhere on a posted entry
  • PeriodStatus · CutoffWarning — the period state machine
  • RollForward · ScheduleTable · AccountTieOut · SchedulePreview
  • AuditTrail · EvidencePanel
  • IntegrityCheckPanel with all eleven assertions wired

Exit gate: post an entry, reverse it, and prove from the UI alone that history was never rewritten. Every balance sheet account has a tie-out, and a failing tie-out owns the screen.


M4 — Statements

The differentiator. Nothing else in the ecosystem has this.

  • StatementTable · StatementRow · Rule in anger
  • ProfitAndLoss · BalanceSheet · CashFlowStatement
  • StatementToolbar · PeriodPicker (fiscal-aware) · VarianceCell
  • DrilldownSheet · FluxAnalysis
  • Full statement semantics for screen readers
  • Print stylesheet — multi-page, repeating headers, no orphaned totals
  • Phone presentation: one period at a time, swipeable, fixed label column

Exit gate: an accountant who closes books reviews a rendered P&L and balance sheet and finds nothing wrong. That's the real test, and it should happen before the code is called stable.

Why here: it's the hardest thing to retrofit, the biggest differentiator, and it stress-tests the primitives harder than anything else.


M4.5 — The close

Deliverable: the workflow the statements exist for. This is the Numeric/FloQast lane, operating on the same components that render the statements rather than beside them.

  • CloseStatus — the seven-section gated pipeline
  • CloseChecklist with owners, blockers, weighted progress, and audited sign-off
  • ReconciliationView with basis-stated match suggestions + CategoryPicker with inline rule creation
  • FluxAnalysis — required explanations on material variances, with drivers
  • MaterialityPolicy · RestatementBanner · SubsequentEventLog
  • ApprovalChain · ApprovalInbox (mobile-first) · RoleMatrix

Exit gate: a full month-end close run end to end in the product, by someone who closes books for a living, with no spreadsheet.


M5 — Receivables (AR)

  • InvoiceForm with the per-line revenue-recognition preview · InvoiceDetail · InvoiceRegister
  • AgingTable tied to the AR control account
  • CashApplication + PaymentSuggestion — every case, not the happy path
  • UnappliedCashPanel · CreditNoteForm · CustomerStatement
  • CollectionsWorklist with promise-to-pay · DunningTimeline
  • RevenueWaterfall from performance obligations

Exit gate: a lump-sum payment covering seven invoices with a short pay and a bank fee applies correctly, with every difference given an explicit disposition.


M6 — Payables (AP)

  • BillForm + DuplicateBillAlert (blocking) · BillDetail · BillRegister
  • ThreeWayMatch with line-level variance · MatchExceptionQueue
  • ApprovalChain version-binding — editing a bill voids its approvals
  • PaymentRunBuilder · PaymentRunPreview with hold-to-confirm and resulting cash
  • VendorMaster with versioned bank details · BankDetailChangeAlert
  • ExpenseCapture (camera-first) · CardTransactionMatch
  • UninvoicedReceiptsReport driving the GR/IR accrual

Exit gate: segregation of duties cannot be bypassed by any path in the UI, and a vendor bank-detail change before a payment run is impossible to miss.


M7 — Payments

  • AmountInput — with the full parse/format/caret test suite
  • PaymentForm · CurrencySelect · PayeeSelect · PaymentMethodList
  • ConfirmPaymentDialog · HoldToConfirm with all accessible fallbacks
  • PaymentStatusTimeline · PaymentSuccess · CheckoutSummary
  • Sheet (Vaul) · Toast (Sonner) configured
  • Full gesture layer: velocity dismissal, boundary damping, pointer capture, multi-touch protection

Exit gate: the whole payment flow completed one-handed on a real iPhone SE, over a throttled network, with VoiceOver on.


M8 — Swaps & FX

  • SwapWidget + the flip · RateLine · RateLock · ConversionBreakdown
  • CurrencyPairChart · RateTicker · SlippageControl · FxExposure
  • Live-value infrastructure: use-live-value, the value flash, throttled aria-live

Exit gate: a rate expiring mid-transaction is handled correctly — the action blocks until the user acknowledges the new rate. Never executes at an unseen rate.


M9 — Charts, dashboard & metrics

  • MoneyChart · MoneyBarChart · WaterfallChart · CategoryBreakdown
  • ChartLegend · ChartTooltip · DataTableToggle
  • DashboardShell · AnomalyCard · RunwayCard · CashCalendar
  • Money Law 2 enforced in tests: assert no animation on data change
  • MetricDefinition — and no metric card ships without one
  • NonGaapReconciliation · MrrBridge · BudgetVsActual · CovenantMonitor

Exit gate: every chart has a working table equivalent; every metric shows its formula with values substituted; the greyscale test passes on all of them.


M10 — Multi-entity & consolidation

  • EntitySelector — standalone vs. consolidated visually distinct
  • ConsolidationView · NciPanel · EliminationEntry
  • IntercompanyMatrix — must net to zero, break types named
  • TranslationSummary · CtaRollForward · FxRevaluation · FxGainLossPanel · RateTable

Exit gate: a three-entity group with two functional currencies consolidates, eliminates, translates, and ties — with the CTA visible as its own equity line.


M11 — Completeness & polish

  • Remaining specified components
  • CommandPalette (motionless), the reconciliation match animation
  • LedgerTable · TrialBalance · AuditorMode · SamplingTool · EvidenceBundle
  • LeaseSchedule · AllowanceRollForward · ForecastTable
  • Full visual regression matrix: every component × {light, dark, forced-colors, signal} × {compact, default, comfortable} × {320, 768, 1280}
  • Motion review pass — every animation at 4× slowdown, frame-stepped
  • An audit pass per shipped surface — three findings maximum, plans written to design-plans/
  • The next-day review on every component

Deferred

Item Gate
corner-shape: squircle Baseline Widely Available. Progressive enhancement, no layout change.
View Transitions Not for in-app finance navigation. Revisit only if interruption handling improves.
Figma library After M4, so it's generated from settled components rather than guiding them.
Additional themes Never as a marketplace. A consumer overrides --accent and --font-display; anything more is a fork.
Vue / Svelte ports After the React system is stable. The tokens and the docs port; the components don't.

Definition of done

A component is stable only when all of these are true:

  1. The four-layer spec exists, was reviewed before the code, and ships in its sibling README.md
  2. The full quality bar passes — every section, 4b included
  3. Every edge case in the checklist has a test or a story
  4. axe clean; keyboard-only pass; VoiceOver and NVDA pass
  5. Visual regression across the full matrix
  6. Motion reviewed at 4× slowdown on a throttled real device
  7. Financial review by someone who has actually closed a month — and for anything in families 9–13, a review against the domain docs clause by clause
  8. The next-day review is done

Merged is not stable. Step 8 is not optional — it catches more real problems than every automated check combined.

Told when this spec changes

The docs are the contract the components are built against. When one changes, the component changes with it — and the copy in your repo does not. One email when that happens.

One address, no list rental, unsubscribe in one click.

Works in your QuickBooks Online or Xero file

Get your books closed every month

Lopifi is building AI bookkeeping that keeps your books closed on US GAAP as transactions happen, with a CPA review every quarter, for $200 a month. We’re not open yet.

$200/month when we open. No card now.