You are browsing as a guest. Sign up (or log in) to start making projects!

Flujo

  • 8 Devlogs
  • 54 Total hours

A personal expense tracker called Flujo, built with an editorial / ledger aesthetic instead of the usual finance app look. The goal is to make understanding your own money feel calm and intentional, like keeping a private book of accounts rather than scrolling through dashboards.

Ship #1 Pending review

What did you make?
A personal expense tracker called Flujo, built with an editorial / ledger aesthetic. The app tracks income and expenses with categories, a 5-day forecast visualization, an OCR ticket scanner, and a full debt and shared expenses system for tracking who owes whom between flatmates or friends.
Everything is local-first, stored in localStorage, no account, no server, no tracking.

Built in four betas. Beta 1 was the basics: add expenses, browse by month, summary totals. Beta 2 added a Sankey diagram showing money flow from income to expense categories, a stacked bar chart for the last 6 months, and a donut chart for category breakdown, all drawn on canvas with vanilla JS (no charting library). Beta 3 added a tabbed interface (resumen, apuntes, tickets, deudas) and an OCR ticket scanner using Tesseract.js that extracts products and prices from receipt photos.
Beta 4 added the debts system with four split methods (equal, by shares, exact, by percentage), a greedy algorithm to settle debts with minimum transfers, pattern detection for subscriptions and recurring expenses, plus a dark mode and ES/EN language toggle.

What was challenging?
The Sankey diagram was the hardest part. My first version drew two separate bezier curves joined at the ends, which looked angular and flat and kinda ugly ngl.
Asked another AI for help and it spotted a missing lineTo, but the real fix was using a single bezierCurveTo per ribbon with control points at 42 percent of the horizontal distance (the same proportion D3 uses).
Also had to make both sides share the same scale so ribbons flow horizontally instead of diagonal. The proportional sizing was another bug: I had a minimum height of 38px, so a 10 euro expense looked the same as a 400 euro income. Fixed by dropping the minimum to 3px.

The OCR scanner had a silent bug where it would hang forever on “procesando imagen”. I was calling tesseractCargado.createWorker where
tesseractCargado is a boolean, not the Tesseract library object. So I was doing true.createWorker which throws a TypeError that nobody caught. Fixed by calling Tesseract.createWorker and added a 90 second timeout.

The internationalization had a sneaky bug too. The language toggle translated the main UI but left the forecast and debts sections in Spanish because that code was hardcoded from earlier betas. Had to re-translate every section separately.

What are you proud of?
The Sankey diagram, drawn entirely with vanilla canvas, no D3 or any charting library. About 200 lines of math and bezier curves, but the result looks professional. The debt settlement algorithm that minimizes
transfers, so if three people owe each other small amounts it suggests the minimum set of payments instead of everyone paying everyone. The pattern detection that finds subscriptions and projects their annual cost, which is a sobering number to see. And the whole thing works offline with no backend, no account, no tracking.

What should people know so they can test your project?
Open the demo URL. The resumen tab shows the Sankey diagram, bar chart and donut chart. The apuntes tab lets you add expenses and browse them by month. The tickets tab lets you upload a receipt photo and the OCR extracts products and prices automatically. The deudas tab is where you add people and track shared expenses with four split methods, then see the minimum transfers needed to settle all debts. The gear icon in the header opens settings with a dark mode toggle and ES/EN language switch.
Everything is stored locally in the browser, nothing is sent anywhere.

Live demo: https://notjuangamer10.github.io/flujo/
Source: https://github.com/notjuangamer10/flujo

  • 8 devlogs
  • 54h
Try project → See source code →
Open comments for this post

8h 5m 44s logged

Beta 4 of Flujo is up. The biggest one yet, split into two parts
because of the autoescritor’s 10 hour session limit.

Beta 4a added the settings panel with dark mode and language toggle
(ES/EN). The dark mode uses a warm dark brown palette instead of the
usual cold gray, so it still feels editorial. The language toggle
reloads the page to re-translate static text.

Beta 4b added the debts and shared expenses system. You can add people
(flatmates, friends) and track who owes whom. Shared expenses support
four split methods: equal, by shares (e.g. 2:1:1 means one person pays
double), exact amounts per person, and by percentage. The settle-up
section uses a greedy algorithm to minimize the number of transfers
needed to clear all debts, so if three people owe each other small
amounts, it suggests the minimum set of transfers instead of everyone
paying everyone.

Also added pattern detection. The app analyzes your expenses and finds
recurring ones, things you pay the same amount for multiple times. It
separates them into likely subscriptions (same exact amount, repeated)
and general recurring expenses (same description, similar amounts). Shows
the projected annual cost for subscriptions, which is a sobering number
to see.

Next version will be the last: FastAPI backend for sync between phone
and laptop, plus PWA installable.

1
0
77
Open comments for this post

7h 46m 15s logged

Beta 4a of Flujo is up. I’m starting to get tired of being all day coding. Started the debts and shared expenses feature,
plus two settings that were requested on my other projects. First, a theme toggle. The app now supports a dark mode alongside the
default cream paper look. The toggle is in a small settings panel in the
header. The dark palette uses a warm dark brown instead of the usual
cold gray, so it still feels like the editorial aesthetic.Second, multi-language support. The interface can switch between Spanish
and English. Switching reloads the page so all the static text gets
re-translated. The dynamic content (expenses, descriptions) stays in
whatever language the user typed it in.Third, the structure for the debts tab is in place. A new “deudas” tab
appears next to resumen, apuntes and tickets. The HTML is there (persons
form, shared expense form with split method selector, movements list,
settle-up section, patterns section) but the JavaScript logic comes in
Beta 4b. The shared expense form supports four split methods: equal, by
shares (e.g. 2:1:1 means one person pays double), exact amounts per
person, and by percentage.Split this into two parts because of the autoescritor session limit.
4b comes next with all the logic for shared expenses, debt settlement
and pattern detection.

0
0
8
Open comments for this post

6h 25m 33s logged

Beta 4a of Flujo is up. Started the debts and shared expenses feature,
plus two settings that were requested on my other projects.

First, a theme toggle. The app now supports a dark mode alongside the
default cream paper look. The toggle is in a small settings panel in the
header. The dark palette uses a warm dark brown instead of the usual
cold gray, so it still feels like the editorial aesthetic.

Second, multi-language support. The interface can switch between
Spanish and English. Switching reloads the page so all the static text
gets re-translated. The dynamic content (expenses, descriptions) stays
in whatever language the user typed it in.

Third, the structure for the debts tab is in place. A new “deudas” tab
appears next to resumen, apuntes and tickets. The HTML is there
(persons form, shared expense form with split method selector,
movements list, settle-up section, patterns section) but the JavaScript
logic comes in Beta 4b. The shared expense form supports four split
methods: equal, by shares (e.g. 2:1:1), exact amounts per person, and
by percentage. The settle-up section will use a greedy algorithm to
minimize the number of transfers needed to clear all debts.

0
0
26
Open comments for this post

4h 2m 20s logged

Beta 3.1 is a bugfix release. Two issues.

First, the OCR ticket scanner was completely broken. When you uploaded a
photo it would say “procesando imagen” forever and never finish. Turned
out I was calling tesseractCargado.createWorker where tesseractCargado
is a boolean (true), not the Tesseract library object. So I was doing
true.createWorker which is undefined.createWorker which throws a
TypeError that nobody caught. Switched to Tesseract.createWorker and
added a 90 second timeout plus proper try/catch so it can never hang
again.

Second, the Sankey text was blurry. Canvas draws with whatever font is
available at draw time, and if Google Fonts was still loading on the
first render it fell back to Arial which looked bad when scaled by
devicePixelRatio. Fixed by waiting for document.fonts.ready before the
first draw, rounding all Y coordinates to integers so they align with
physical pixels, and redrawing on window resize so the DPR stays
correct.

0
0
3
Open comments for this post

7h 2m 4s logged

Beta 3 is up
Tabs and OCR Update!!
Three changes.

First, the Sankey is now proportional. Before, every node had a minimum
height of 38px, so a 10 euro expense looked the same as a 400 euro
income. Now the minimum is 3px and both sides use the global total as
their scale, so node heights actually reflect the amounts. A 10 euro
category is a tiny sliver next to a 400 euro income source.

Second, added tabs. The app was getting long with everything in one
column. Now there are three tabs: resumen (income sources and charts),
apuntes (the expense form and list), and tickets (new). The tab bar uses
the same editorial styling, lowercase text with an ochre underline on
the active tab.

Third, the big one: OCR ticket scanning. On the tickets tab you upload a
photo of a supermarket receipt and Tesseract.js extracts the text, then
a regex parser pulls out product names and prices. Each detected item
shows up in a list with a checkbox, you pick a category, hit save, and
all items become individual expenses. The parser looks for lines ending
in a decimal number (the classic receipt format) and skips lines that
look like totals, subtotals or payment info.

Tesseract loads from CDN the first time you use it. It runs entirely in
the browser, no server involved, which keeps the local-first promise.
The recognition is decent for clean photos, struggles with crumpled
receipts. The parser is basic but catches most supermarket formats. If
it fails, there is a details panel showing the raw OCR text so you can
see what went wrong.

0
0
11
Open comments for this post

4h 21m 12s logged

Beta 2.1 is a visual rework of the Sankey diagram.
Charts Update!:
The previous version
worked but looked rough: the flow ribbons were angular, the nodes were
plain rectangles, and the two sides used independent scales so the
ribbons went diagonal instead of horizontal.

I asked another AI for help with the algorithm and it suggested a
cleaner approach. Each ribbon is now a single bezier curve with control
points at 42 percent of the horizontal distance (the same proportion D3
uses in its Sankey layout), instead of two curves joined at the ends.
The nodes are rounded rectangles with a soft shadow. Both sides share
the same scale so the ribbons flow straight. Nodes are centered
vertically instead of pinned to the top.

I kept the editorial palette: dark green for income nodes, black ink for
the center “total” node, cream with a colored accent stripe for each
expense category. The ribbons use the category color at 30 percent
opacity so overlaps create natural layering.

Also fixed a timezone bug in the 6 month bar chart. I was using
toISOString to build the month key, which converts to UTC and can return
the wrong month near midnight. Switched to getFullYear and getMonth
which stay in local time. The bars were technically drawing before but
some months were mismatched, now they line up correctly.
I still have to work that better, but it isnt thaaat bad

0
0
4
Open comments for this post

8h 57m 27s logged

Beta 2 of Flujo is up. The big one: a Sankey diagram showing the flow of
your money, income sources on the left, expense categories on the right,
with smooth flowing ribbons in between. Drawn on canvas with vanilla JS,
no D3 or any charting library. Just bezierCurveTo and a lot of math.

Also added two more charts: a stacked bar chart showing the last 6 months
(each bar broken down by category, with the monthly total on top), and a
donut chart for the current month’s category breakdown with a legend.

To make the Sankey meaningful I had to add an income system, a small
form where you register your income sources (scholarship, parents, job,
etc.). The balance section now shows five numbers: spent, count, average,
income, and balance (green if positive, red if negative).

The Sankey was the hardest part. My first version drew two separate
bezier curves (top and bottom) and joined them at the ends, the ribbons
looked flat and angular, like triangles. I asked Gemini for help and it
spotted a missing lineTo at the destination node, which fixed the pinch.
But the ribbons still looked off. Turned out the real problem was the
algorithm: each ribbon needs to be ONE single bezierCurveTo with four
control points (not two curves joined), and both sides need to share the
same scale (not normalize independently). Once I fixed that, the ribbons
flowed organically like a real Sankey.

The bar chart had a sneaky bug too: it drew the grid lines but no bars.
Took me a while, I was using canvas.clientWidth (DOM size) instead of
canvas.width (drawing context size). The CSS makes the canvas visually
smaller than its internal resolution, so the bars were being drawn
outside the visible area. Classic canvas gotcha.

Used a muted, desaturated palette for the 8 categories (ochre, dusty
blue, sage green, etc.) instead of bright primary colors, keeps the
editorial aesthetic intact.

Next version will be the OCR ticket scanner, organized in tabs so the
charts don’t compete with the expense list for space. And also redigning the sankey because i dont like how it looks.

0
0
12
Open comments for this post

7h 17m 53s logged

Started a new project called Flujo, a personal expense tracker. The idea
was to make something that doesn’t look like every other finance app
most of them use blue or green with cards and Material-style shadows.

I went with an “editorial ledger” aesthetic: paper cream background, dark
ink text, an ochre accent, and three typefaces working together Fraunces
(a serif) for titles, Inter Tight for UI, and JetBrains Mono with tabular
numerals for the amounts so they align like a real accounting book.

Beta 1 is the basics: a form to add an expense (amount, category,
description, date), a list of expenses for the current month with running
numbers (001, 002…), and three totals on top spent, count, and average.
There’s a month selector in the header. Everything lives in localStorage,
no backend, no server, no tracking.

The list is called “libro mayor” (general ledger) and each entry is an
“apunte” (bookkeeping entry) small details that lean into the book
metaphor. Next version will add the Sankey diagram and bar charts.

0
0
18

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…