Portfolio/SpendWell
πŸ’³ Personal Finance Β· Fintech Β· Full-Stack

SpendWell

A personal-finance app that turns a pile of mismatched bank exports and paper supermarket receipts into clean, categorized, item-level spending insight, designed and built end to end.

Role
Design + Full-Stack (solo)
Timeline
2024 – Present
Type
Personal product
Platform
Web Β· React + NestJS
app.spendwell.io
SpendWell
πŸŒ™ Dark
Dashboard
Expenses
Bills
Services
Payment Plans
Household
Receipts
Item Insights
Welcome Mario πŸ‘‹
Home / Dashboard
March 2026 ▾⬆ ImportAdd Expenses
Total spending (inc. Bills)
$1,842.0
πŸ’°
See all β†’
Bills & Services
$612.4
🧾
See all β†’
Purchases
$1,229.6
πŸ›οΈ
See all β†’
Savings
$958.0
πŸ’΅
See all β†’
Recent Transactions
Carrefour Market
Mar 4
-94.12 €
SNCF Connect
Mar 4
-48.00 €
Amazon EU
Mar 3
+31.90 €
Boulangerie Utopie
Mar 3
-8.40 €
EDF
Mar 2
-74.10 €
Spending Β· this year vs last
This yearLast year
Top Categories
Groceries€612.00
Bills€388.00
Transport€214.00
Dining€176.00
Shopping€143.00

Personal finance
without the spreadsheet.

Bank CSVs don’t agree with each other, and none of the big trackers read a French ticket de caisse down to the line item. SpendWell exists to close that gap.

The goal is totals you can trust: a refund is its own kind of transaction, never a negative purchase, so the monthly figure never quietly drifts. Designed and built end to end, and I use it on my own money every week.

TypePersonal product, in daily use
UsersIndividuals & households
ScopeProduct design through full-stack build
Front endReact 19, TypeScript, Tailwind v4, Vite
Back endNestJS, Firebase, PDF receipt parsing
StatusLive Β· actively iterated

Not another budget app.
A ledger that stays honest.

SpendWell earns its place on the two things the incumbents skip: local bank formats and receipt-level detail.

01
The user
Tried YNAB, Bankin', or a spreadsheet and stopped. Wants the truth about last month with minimal fuss.
02
Where it wins
French and Revolut exports parsed without column mapping, receipts read down to the line item.
03
The non-goals
No bank API aggregation, no investment tracking, no advice. It records what happened, accurately.

Three reasons budgeting
never stuck.

Every manual budget broke down at the same three points.

01
Statements don't agree
Every bank exports a different CSV shape. Each month meant re-mapping columns by hand.
02
A grocery run is one number
β€œβ‚¬94.12 at Carrefour” tells you nothing β€” the detail lives on a receipt that gets thrown away.
03
The totals quietly drift
Refunds get added instead of subtracted, bills double-count, and the number you budget against is wrong.

Three decisions
in the data model.

Most of the design work here is invisible β€” it lives in how money is modelled.

01
A refund is its own transaction
The common shortcut stores a refund as a negative expense β€” a €30 refund quietly cancels €30 of spend that never stopped. Modelling it as a distinct type is why a month's total always reconciles.
Data modelCorrectness
02
Import you can run twice
Statements overlap at month boundaries, so every row is fingerprinted β€” re-importing an overlapping export is a no-op. The import button stops being scary.
IdempotencyTrust
03
Match receipts across all history
Receipts get uploaded in batches, weeks late, so matching searches the whole history, not just the current month. A receipt scanned in March still finds its January transaction.
MatchingTrade-off

Expenses

Every transaction, filterable by category, with the real left-hand sub-nav for switching between the list, the yearly view, and the highest-categories breakdown.

Bills

Recurring, fixed-amount charges, rent, electricity, internet, with a running monthly total at the top.

Services

The same list-plus-total pattern as Bills, for subscriptions: streaming, mobile plans, memberships.

Payment Plans

Installment purchases tracked to payoff, status and a progress bar per plan, not just a single due date.

Receipts

Drop in a ticket de caisse PDF and it's parsed line by line and auto-linked to the matching transaction by total.

Item Insights

A year of receipts turned into per-product purchase counts and spend, the payoff for itemizing every receipt.

Two more worth a look.

The pieces it's made of.

Buttons
Add ExpensesImport
Filter chips
All128Dining19
Category pills
GroceriesTransportDiningBillsShopping
Status chips
activecompletedpaused
Receipt badges
LinkedUnlinked
KPI card
Savings
$958.0
πŸ’΅
See all β†’
Progress bar
Stat tone chips
●●●●
Household avatar
MA
Theme pill
πŸŒ™ Dark

Built to be used
every week.

Figures are illustrative; the interface mockups on this page are reconstructions of the real UI, not screenshots of real financial data.

6
Bank & card formats
French banks and Revolut, detected on import
3y
Of statements in one place
Consolidated into a single clean ledger
90%
Categorized automatically
On import, before any manual review
100%
Of receipts itemized
Store, date, line items and total, then linked
60+
Product groups tracked
In the yearly Item Insights dashboard
0
Duplicate imports
Overlapping statements are skipped automatically

What I’d change. Reading a French ticket de caisse is still the weak link: thermal-print receipts are noisy, so the review queue for low-confidence line items needs to be shorter than it is.

Next Project
StockFlow
A smart B2B logistics platform for order management, shipment tracking, returns, and inventory.
View project β†’