Skip to content
Back

SaldoCerto

Personal projectRole: Sole developerFlutterRiverpodSupabaseSQLite

Flutter personal-finance app built around your salary: category budgets, expenses, fixed bills and goals. Offline-first, on Supabase with RLS, with an AI assistant that never sees your numbers.

SaldoCerto

// Overview

A Flutter app that organizes your finances around your salary: the month's income is split into budget categories, expenses and fixed bills are logged, and a chart dashboard shows how much is actually left.

// The challenge

Money tracking fails in two places. The first is the moment of the expense: at the store or on the bus, with no signal, an app that needs the network just doesn't record it. The second is privacy: an AI assistant that reads your finances is a question of trust before it is a feature.

// Constraints

Record the expense where it happens, including with no signal — and no financial figure may ever reach an AI model.

// Engineering decisions

Offline-first

Choice
a SQLite mirror of the Supabase data and a mutation queue (outbox) that every repository goes through.
Why
expenses are logged where there is no signal — at the store, on the bus.
Trade-off
more sync complexity, in exchange for the app never refusing a record.

AI without financial data

Choice
the model only interprets the question; the math runs in Postgres functions under RLS and the answer is assembled in code.
Why
an assistant that reads your finances is a question of trust before it is a feature.
Trade-off
the assistant only answers what the database functions can compute.

// The solution

Real offline-first: a SQLite mirror of the Supabase data and a mutation queue (outbox) that every repository goes through — a write made without network is queued and replayed when the connection returns. On the server, Postgres with RLS on every table. The assistant uses LLMs only to understand the question, in a free cascade with fallback (Groq → OpenRouter → keyword router); the math runs in Postgres functions under RLS and the answer is assembled in code. No financial figure ever reaches a model.

// Architecture

Architecture diagram of SaldoCerto's offline-first design. The Flutter UI (Riverpod and go_router) only talks to the repositories. Each repository reads from the local SQLite mirror and writes to a mutation queue (outbox); when the connection returns, the queue is replayed on Supabase, a Postgres database with RLS on every table. Separately, the assistant: an LLM, in a Groq, OpenRouter and keyword-router cascade, only interprets the question; the math runs in Postgres functions under RLS and the answer is assembled in code — no financial figure goes to the model.

My role

Sole developer — product, architecture (Riverpod + go_router, 20+ feature modules), database (42 Supabase migrations), tests and the release pipeline.

Tech stack

FlutterDartRiverpodgo_routerSupabasePostgreSQLSQLiteFirebase CrashlyticsGitHub Actions

// Screens

Dashboard with today's safe-to-spend amount, available balance and month-end projection
Monthly transactions grouped by day, with category, date and amount
Category budgets comparing spending against each monthly limit
Savings goals with progress, target date and suggested monthly contribution
Dark theme: donut chart of spending by category and monthly budgets

// Outcome and evidence

Version 1.40, with releases automated by Release Please. 88 test files and 550+ test cases, including full-app E2E running on an emulator in CI. The source is private.

test cases
550+
including full-app E2E on an emulator in CI
Supabase migrations
42
feature modules
20+

Looking for this kind of work?