← All projects

Personal project · 2026

Reparte

A personal budgeting app: enter what you earned this month and it tells you how much to set aside for bills, savings, investment, leisure, activities and unexpected costs. Works offline; the data never leaves the device.

The source code is in a private repository; the public reparte-app repository only contains the built app. The interface is in Portuguese.

Problem

Fixed-percentage budgeting rules (50/30/20 and similar) break down when income changes from month to month. In a weak month, what gets cut first? In a good month, where does the surplus go — and why?

Context and motivation

I wanted a concrete answer to "I got paid X — how much goes where?", with clear priorities and an explanation in plain language: no bank connections, no accounts, and no data sent anywhere.

What I built

Individual project: the data model and allocation algorithm, the interface, the tests and the PWA release.

Where the logic lives

  1. 01 Interface

    • Allocate
    • History
    • Settings
  2. 02 Domain

    • allocate(income, settings, balances)
    • Bills → minimums → buffer → leisure and activities → surplus
    • Plain-language explanation
  3. 03 Guarantees

    • Integer cents, never floats
    • Largest-remainder splitting
    • Parts always sum to the income
  4. 04 Storage

    • localStorage with a schema version
    • JSON backup and import
    • PWA: works offline
Reparte's layers: the algorithm is a pure function with no React and no storage.

Technical decisions

4

Priorities, not percentages

Bills come first, in list order; then minimum savings and investment, the buffer for unexpected costs, and only then leisure and activities. Any surplus is split by configurable rules with caps. In a tight month, cuts are made from the bottom up and the app says exactly what was reduced.

Money as integer cents

There are no floats in the calculation. Proportional splits use the largest-remainder method, so the parts always add up exactly to the income — an invariant checked in every test scenario.

The domain knows nothing about React

The algorithm is a pure function, allocate(income, settings, goalBalances), isolated in src/domain. Moving to a backend or a mobile app means replacing the storage layer, not touching the calculation.

Simple where it can be

Three screens don't justify a router, a charting library or a state manager. Data lives in localStorage with a schema version for migrations, plus JSON backup and import.

What it does

  • Monthly allocation with a written explanation and transfers grouped by account
  • Deficit, tight, normal and surplus states, listing anything left uncovered
  • Savings and investment goals with shares and targets
  • Immutable monthly history and month-to-month comparison
  • Portuguese number formats ("1.500,50 €")
  • Installable and usable offline

Evidence

what was checked, and how
WhatResultSourceChecked
Automated tests68 passedVitest run locally on the domain layer (algorithm, investment, scenarios, usage)
Published appOnline (HTTP 200)Request to the GitHub Pages build

Limitations and next steps

Known limitations

  • Data lives only in each device's browser; there is no sync.
  • It does not connect to banks or import transactions — it is a planning tool, not an expense tracker.