
A physical piggy bank has one frustrating property: you can add cash easily, but you cannot see the total without counting its contents. PennyTap is an Android app that records each deposit so the total and progress toward a savings goal remain visible.
The interface is deliberately small: choose a cash denomination or enter an amount, set a goal, and review a history of deposits. The interesting engineering work is in keeping those numbers honest. Here are three decisions from the PennyTap codebase that other developers building a small local tracker may find useful.
1. Store deposits as entries, then calculate the total
PennyTap keeps an array of entries. Each entry has an amount, a creation time, an ID, and an optional note. Adding money creates a new entry at the start of the list. The total is calculated by adding the amounts in that list; it is not maintained as a separate saved counter.
That choice makes corrections easier to reason about. If someone removes an accidental entry or edits an amount, the next total comes from the entries that remain. The goal progress is then total / goal when a positive goal exists. The progress bar limits its displayed width, while the underlying progress can exceed 100% if someone saves more than planned.
A small tracker still needs to distinguish a record from a bank balance. PennyTap records what a person says they put into a physical piggy bank. It cannot verify the cash inside, and it does not connect to a financial account. That distinction shapes the language in the app and the expectations around its numbers.
2. Load local data before saving changes
The app persists its state with AsyncStorage: entries, goal, goal note, and selected currency. On launch, it loads that state into React state. A loaded flag prevents the save effect from running before the stored data has been read.
Without that guard, the initial empty state could overwrite a person's saved entries during startup. This is a modest implementation detail with a large effect on trust: losing a savings history would make the tracker much less useful.
The stored object also has a schema version. When an older record lacks that version, PennyTap marks those entries as legacy. Their notes can still be edited, but their amounts are locked so an older total is not silently rewritten. The settings screen also provides an export and restore flow for the saved data.
3. Treat currency changes as a data decision
PennyTap supports VND, USD, EUR, and GBP. Each currency has its own preset cash denominations and formatting. The interface language is a separate choice: the app reads the device locale and currently provides English and Vietnamese text.
A common shortcut would be to switch a currency symbol and keep the same entries. That would turn a recorded amount of 50,000 VND into 50,000 USD without a conversion, which is misleading. PennyTap instead asks for confirmation, then clears the existing entries and goal when the currency changes. This behavior is explicit in the settings screen.
There may be richer ways to handle multiple currencies in a future version, such as retaining a currency per entry. For this app's current single-currency model, an explicit reset is easier to understand than displaying an incorrect total.
The product lesson
A small app does not need a complex data model, but it does need clear rules for what a number means. In PennyTap, the entry list is the source for the total, saved data is loaded before new state is written, and changing currency requires a deliberate choice. Those rules help the visible total remain understandable.
Top comments (0)